Merge branch 'master' into simulator
[platform/upstream/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);"
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             { OC_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"
74 #define PDM_SQLITE_GET_UUID "SELECT UUID FROM T_DEVICE_LIST WHERE ID = ?"
75 #define PDM_SQLITE_GET_LINKED_DEVICES "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
76 #define PDM_SQLITE_GET_DEVICE_LINKS "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE ID = ? and ID2 = ?"
77
78 #define ASCENDING_ORDER(id1, id2) do{if( (id1) > (id2) )\
79   { int temp; temp = id1; id1 = id2; id2 = temp; }}while(0)
80
81 #define CHECK_PDM_INIT(tag) do{if(true != gInit)\
82   { OC_LOG(ERROR, (tag), "PDB is not initialized"); \
83     return OC_STACK_PDM_IS_NOT_INITIALIZED; }}while(0)
84
85 static sqlite3 *g_db = NULL;
86 static bool gInit = false;  /* Only if we can open sqlite db successfully, gInit is true. */
87
88 /**
89  * function to create DB in case DB doesn't exists
90  */
91 static OCStackResult createDB(const char* path)
92 {
93
94     int result = 0;
95     result = sqlite3_open_v2(path, &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
96     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
97
98     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LIST, NULL, NULL, NULL);
99     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
100
101     OC_LOG(INFO, TAG, "Created T_DEVICE_LIST");
102     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LINK, NULL, NULL, NULL);
103     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
104
105     OC_LOG(INFO, TAG, "Created T_DEVICE_LINK_STATE");
106     gInit = true;
107     return OC_STACK_OK;
108 }
109
110
111 /**
112  * Function to begin any transaction
113  */
114 static OCStackResult begin()
115 {
116     int res = 0;
117     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_BEGIN, NULL, NULL, NULL);
118     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
119     return OC_STACK_OK;
120 }
121
122 /**
123  * Function to commit any transaction
124  */
125 static OCStackResult commit()
126 {
127     int res = 0;
128     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_COMMIT, NULL, NULL, NULL);
129     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
130     return OC_STACK_OK;
131 }
132
133 /**
134  * Function to rollback any transaction
135  */
136 static OCStackResult rollback()
137 {
138     int res = 0;
139     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_ROLLBACK, NULL, NULL, NULL);
140     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
141     return OC_STACK_OK;
142 }
143
144 /**
145  * Error log callback called by SQLite stack in case of error
146  */
147 void errLogCallback(void *pArg, int iErrCode, const char *zMsg)
148 {
149     (void) pArg;
150     (void) iErrCode;
151     (void) zMsg;
152     OC_LOG_V(DEBUG,TAG, "(%d) %s", iErrCode, zMsg);
153 }
154
155 OCStackResult PDMInit(const char *path)
156 {
157     int rc;
158     const char *dbPath = NULL;
159     if (SQLITE_OK !=  sqlite3_config(SQLITE_CONFIG_LOG, errLogCallback, NULL))
160     {
161         OC_LOG(INFO, TAG, "Unable to enable debug log of sqlite");
162     }
163
164     if (NULL == path || !*path)
165     {
166         dbPath = DB_FILE;
167     }
168     else
169     {
170         dbPath = path;
171     }
172     rc = sqlite3_open_v2(dbPath, &g_db, SQLITE_OPEN_READWRITE, NULL);
173     if (SQLITE_OK != rc)
174     {
175         OC_LOG_V(INFO, TAG, "ERROR: Can't open database: %s", sqlite3_errmsg(g_db));
176         return createDB(dbPath);
177     }
178     gInit = true;
179     return OC_STACK_OK;
180 }
181
182
183 OCStackResult PDMAddDevice(const OicUuid_t *UUID)
184 {
185     CHECK_PDM_INIT(TAG);
186     if (NULL == UUID)
187     {
188         return OC_STACK_INVALID_PARAM;
189     }
190
191     sqlite3_stmt *stmt = 0;
192     int res =0;
193     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_T_DEVICE_LIST,
194                               strlen(PDM_SQLITE_INSERT_T_DEVICE_LIST) + 1, &stmt, NULL);
195     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
196
197     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
198     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
199
200     res = sqlite3_step(stmt);
201     if (SQLITE_DONE != res)
202     {
203         if (SQLITE_CONSTRAINT == res)
204         {
205             //new OCStack result code
206             OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
207             sqlite3_finalize(stmt);
208             return OC_STACK_DUPLICATE_UUID;
209         }
210         OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
211         sqlite3_finalize(stmt);
212         return OC_STACK_ERROR;
213     }
214     sqlite3_finalize(stmt);
215     return OC_STACK_OK;
216 }
217
218 /**
219  *function to get Id for given UUID
220  */
221 static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
222 {
223     sqlite3_stmt *stmt = 0;
224     int res = 0;
225     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
226     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
227
228     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
229     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
230
231     OC_LOG(DEBUG, TAG, "Binding Done");
232     while (SQLITE_ROW == sqlite3_step(stmt))
233     {
234         int tempId = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
235         OC_LOG_V(DEBUG, TAG, "ID is %d", tempId);
236         *id = tempId;
237         sqlite3_finalize(stmt);
238         return OC_STACK_OK;
239     }
240     sqlite3_finalize(stmt);
241     return OC_STACK_INVALID_PARAM;
242 }
243
244 /**
245  * Function to check duplication of device's Device ID.
246  */
247 OCStackResult PDMIsDuplicateDevice(const OicUuid_t* UUID, bool *result)
248 {
249
250     CHECK_PDM_INIT(TAG);
251     if (NULL == UUID || NULL == result)
252     {
253         OC_LOG(ERROR, TAG, "UUID or result is NULL");
254         return OC_STACK_INVALID_PARAM;
255     }
256     sqlite3_stmt *stmt = 0;
257     int res = 0;
258     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
259     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
260
261     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
262     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
263
264     OC_LOG(DEBUG, TAG, "Binding Done");
265     bool retValue = false;
266     while(SQLITE_ROW == sqlite3_step(stmt))
267     {
268         OC_LOG(INFO, TAG, "Duplicated UUID");
269         retValue = true;
270     }
271
272     sqlite3_finalize(stmt);
273     *result = retValue;
274     return OC_STACK_OK;
275 }
276
277 /**
278  * Function to add link in sqlite
279  */
280 static OCStackResult addlink(int id1, int id2)
281 {
282     sqlite3_stmt *stmt = 0;
283     int res = 0;
284     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_LINK_DATA,
285                               strlen(PDM_SQLITE_INSERT_LINK_DATA) + 1, &stmt, NULL);
286     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
287
288     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
289     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
290
291     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
292     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
293
294     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
295     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
296
297     if (sqlite3_step(stmt) != SQLITE_DONE)
298     {
299         OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
300         sqlite3_finalize(stmt);
301         return OC_STACK_ERROR;
302     }
303     sqlite3_finalize(stmt);
304     return OC_STACK_OK;
305 }
306
307 OCStackResult PDMLinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
308 {
309     CHECK_PDM_INIT(TAG);
310     if (NULL == UUID1 || NULL == UUID2)
311     {
312         OC_LOG(ERROR, TAG, "Invalid PARAM");
313         return  OC_STACK_INVALID_PARAM;
314     }
315     int id1 = 0;
316     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
317     {
318         OC_LOG(ERROR, TAG, "Requested value not found");
319         return OC_STACK_INVALID_PARAM;
320     }
321     int id2 = 0;
322     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
323     {
324         OC_LOG(ERROR, TAG, "Requested value not found");
325         return OC_STACK_INVALID_PARAM;
326     }
327     ASCENDING_ORDER(id1, id2);
328     return addlink(id1, id2);
329 }
330
331 /**
332  * Function to remove created link
333  */
334 static OCStackResult removeLink(int id1, int id2)
335 {
336     int res = 0;
337     sqlite3_stmt *stmt = 0;
338     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_LINK, strlen(PDM_SQLITE_DELETE_LINK) + 1, &stmt, NULL);
339     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
340
341     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
342     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
343
344     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
345     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
346
347     if (SQLITE_DONE != sqlite3_step(stmt))
348     {
349         OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
350         sqlite3_finalize(stmt);
351         return OC_STACK_ERROR;
352     }
353     sqlite3_finalize(stmt);
354     return OC_STACK_OK;
355 }
356
357 OCStackResult PDMUnlinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
358 {
359     CHECK_PDM_INIT(TAG);
360     if (NULL == UUID1 || NULL == UUID2)
361     {
362         OC_LOG(ERROR, TAG, "Invalid PARAM");
363         return  OC_STACK_INVALID_PARAM;
364     }
365
366     int id1 = 0;
367     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
368     {
369         OC_LOG(ERROR, TAG, "Requested value not found");
370         return OC_STACK_INVALID_PARAM;
371     }
372
373     int id2 = 0;
374     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
375     {
376         OC_LOG(ERROR, TAG, "Requested value not found");
377         return OC_STACK_INVALID_PARAM;
378     }
379     ASCENDING_ORDER(id1, id2);
380     return removeLink(id1, id2);
381 }
382
383 static OCStackResult removeFromDeviceList(int id)
384 {
385     sqlite3_stmt *stmt = 0;
386     int res = 0;
387     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_DEVICE,
388                               strlen(PDM_SQLITE_DELETE_DEVICE) + 1, &stmt, NULL);
389     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
390
391     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
392     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
393
394     if (sqlite3_step(stmt) != SQLITE_DONE)
395     {
396         OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
397         sqlite3_finalize(stmt);
398         return OC_STACK_ERROR;
399     }
400     sqlite3_finalize(stmt);
401     return OC_STACK_OK;
402 }
403
404 OCStackResult PDMDeleteDevice(const OicUuid_t *UUID)
405 {
406     CHECK_PDM_INIT(TAG);
407     if (NULL == UUID)
408     {
409         return OC_STACK_INVALID_PARAM;
410     }
411     int id = 0;
412     if (OC_STACK_OK != getIdForUUID(UUID, &id))
413     {
414         OC_LOG(ERROR, TAG, "Requested value not found");
415         return OC_STACK_INVALID_PARAM;
416     }
417     begin();
418     if(OC_STACK_OK != removeFromDeviceList(id))
419     {
420         rollback();
421         OC_LOG(ERROR, TAG, "Requested value not found");
422         return OC_STACK_ERROR;
423     }
424     commit();
425     return OC_STACK_OK;
426 }
427
428
429 static OCStackResult updateLinkState(int id1, int id2, int state)
430 {
431     sqlite3_stmt *stmt = 0;
432     int res = 0 ;
433     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK,
434                               strlen(PDM_SQLITE_UPDATE_LINK) + 1, &stmt, NULL);
435     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
436
437     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
438     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
439
440     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id1);
441     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
442
443     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, id2);
444     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
445
446     if (SQLITE_DONE != sqlite3_step(stmt))
447     {
448         OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
449         sqlite3_finalize(stmt);
450         return OC_STACK_ERROR;
451     }
452     sqlite3_finalize(stmt);
453     return OC_STACK_OK;
454 }
455
456 OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2)
457 {
458     CHECK_PDM_INIT(TAG);
459     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2)
460     {
461         OC_LOG(ERROR, TAG, "Invalid PARAM");
462         return  OC_STACK_INVALID_PARAM;
463     }
464
465     int id1 = 0;
466     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
467     {
468         OC_LOG(ERROR, TAG, "Requested value not found");
469         return OC_STACK_INVALID_PARAM;
470     }
471
472     int id2 = 0;
473     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
474     {
475         OC_LOG(ERROR, TAG, "Requested value not found");
476         return OC_STACK_INVALID_PARAM;
477     }
478     ASCENDING_ORDER(id1, id2);
479     return updateLinkState(id1, id2, PDM_STALE_STATE);
480
481 }
482
483 OCStackResult PDMGetOwnedDevices(OCUuidList_t **uuidList, size_t *numOfDevices)
484 {
485     CHECK_PDM_INIT(TAG);
486     if (NULL != *uuidList)
487     {
488         OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
489         return OC_STACK_INVALID_PARAM;
490     }
491     sqlite3_stmt *stmt = 0;
492     int res = 0;
493     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_LIST_ALL_UUID,
494                               strlen(PDM_SQLITE_LIST_ALL_UUID) + 1, &stmt, NULL);
495     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
496
497     int counter  = 0;
498     while (SQLITE_ROW == sqlite3_step(stmt))
499     {
500
501         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
502         OicUuid_t *uid = (OicUuid_t *)ptr;
503         OCUuidList_t *temp = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
504         if (NULL == temp)
505         {
506             OC_LOG_V(ERROR, TAG, "Memory allocation problem");
507             sqlite3_finalize(stmt);
508             return OC_STACK_NO_MEMORY;
509         }
510         memcpy(&temp->dev.id, uid->id, UUID_LENGTH);
511         LL_PREPEND(*uuidList,temp);
512         ++counter;
513     }
514     *numOfDevices = counter;
515     sqlite3_finalize(stmt);
516     return OC_STACK_OK;
517 }
518
519 static OCStackResult getUUIDforId(int id, OicUuid_t *uid)
520 {
521     sqlite3_stmt *stmt = 0;
522     int res = 0;
523     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_UUID,
524                               strlen(PDM_SQLITE_GET_UUID) + 1, &stmt, NULL);
525     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
526
527     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
528     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
529
530     while (SQLITE_ROW == sqlite3_step(stmt))
531     {
532         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
533         memcpy(uid, ptr, sizeof(OicUuid_t));
534     }
535     sqlite3_finalize(stmt);
536     return OC_STACK_OK;
537 }
538
539 OCStackResult PDMGetLinkedDevices(const OicUuid_t *UUID, OCUuidList_t **UUIDLIST, size_t *numOfDevices)
540 {
541     CHECK_PDM_INIT(TAG);
542     if (NULL != *UUIDLIST)
543     {
544         OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
545         return OC_STACK_INVALID_PARAM;
546     }
547     if (NULL == UUID)
548     {
549         return OC_STACK_INVALID_PARAM;
550     }
551     int id = 0;
552     if (OC_STACK_OK != getIdForUUID(UUID, &id))
553     {
554         OC_LOG(ERROR, TAG, "Requested value not found");
555         return OC_STACK_INVALID_PARAM;
556     }
557
558     sqlite3_stmt *stmt = 0;
559     int res = 0;
560     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_LINKED_DEVICES,
561                               strlen(PDM_SQLITE_GET_LINKED_DEVICES) + 1, &stmt, NULL);
562     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
563
564     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
565     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
566
567     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
568     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
569
570     int counter  = 0;
571     while (SQLITE_ROW == sqlite3_step(stmt))
572     {
573         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
574         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
575
576         OicUuid_t temp = {{0,}};
577         if (i1 != id)
578         {
579             getUUIDforId(i1, &temp);
580         }
581         if (i2 != id)
582         {
583             getUUIDforId(i2, &temp);
584         }
585
586         OCUuidList_t *tempNode = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
587         if (NULL == tempNode)
588         {
589             OC_LOG(ERROR, TAG, "No Memory");
590             sqlite3_finalize(stmt);
591             return OC_STACK_NO_MEMORY;
592         }
593         memcpy(&tempNode->dev.id, &temp.id, UUID_LENGTH);
594         LL_PREPEND(*UUIDLIST,tempNode);
595         ++counter;
596     }
597     *numOfDevices = counter;
598      sqlite3_finalize(stmt);
599      return OC_STACK_OK;
600 }
601
602 OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t **staleDevList, size_t *numOfDevices)
603 {
604     CHECK_PDM_INIT(TAG);
605     if (NULL != *staleDevList)
606     {
607         OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
608         return OC_STACK_INVALID_PARAM;
609     }
610
611     sqlite3_stmt *stmt = 0;
612     int res = 0;
613     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_STALE_INFO,
614                               strlen(PDM_SQLITE_GET_STALE_INFO) + 1, &stmt, NULL);
615     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
616
617     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_STALE_STATE);
618     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
619
620     int counter  = 0;
621     while (SQLITE_ROW == sqlite3_step(stmt))
622     {
623         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
624         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
625         OicUuid_t temp1 = {{0,}};
626         OicUuid_t temp2 = {{0,}};;
627         getUUIDforId(i1, &temp1);
628         getUUIDforId(i2, &temp2);
629
630         OCPairList_t *tempNode = (OCPairList_t *) OICCalloc(1, sizeof(OCPairList_t));
631         if (NULL == tempNode)
632         {
633             OC_LOG(ERROR, TAG, "No Memory");
634             sqlite3_finalize(stmt);
635             return OC_STACK_NO_MEMORY;
636         }
637         memcpy(&tempNode->dev.id, &temp1.id, UUID_LENGTH);
638         memcpy(&tempNode->dev2.id, &temp2.id, UUID_LENGTH);
639         LL_PREPEND(*staleDevList, tempNode);
640         ++counter;
641     }
642     *numOfDevices = counter;
643     sqlite3_finalize(stmt);
644     return OC_STACK_OK;
645 }
646
647 OCStackResult PDMClose()
648 {
649     CHECK_PDM_INIT(TAG);
650     int res = 0;
651     res = sqlite3_close(g_db);
652     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
653     return OC_STACK_OK;
654 }
655
656 void PDMDestoryOicUuidLinkList(OCUuidList_t* ptr)
657 {
658     if(ptr)
659     {
660         OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
661         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
662         {
663             LL_DELETE(ptr, tmp1);
664             OICFree(tmp1);
665         }
666     }
667 }
668
669 void PDMDestoryStaleLinkList(OCPairList_t* ptr)
670 {
671     if(ptr)
672     {
673         OCPairList_t *tmp1 = NULL,*tmp2=NULL;
674         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
675         {
676             LL_DELETE(ptr, tmp1);
677             OICFree(tmp1);
678         }
679     }
680 }
681
682 OCStackResult PDMIsLinkExists(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2,
683                                bool* result)
684 {
685     CHECK_PDM_INIT(TAG);
686     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2 || NULL == result)
687     {
688         return OC_STACK_INVALID_PARAM;
689     }
690     int id1 = 0;
691     int id2 = 0;
692     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
693     {
694         OC_LOG(ERROR, TAG, "Requested value not found");
695         return OC_STACK_INVALID_PARAM;
696     }
697
698     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
699     {
700         OC_LOG(ERROR, TAG, "Requested value not found");
701         return OC_STACK_INVALID_PARAM;
702     }
703
704     ASCENDING_ORDER(id1, id2);
705
706     sqlite3_stmt *stmt = 0;
707     int res = 0;
708     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_DEVICE_LINKS,
709                               strlen(PDM_SQLITE_GET_DEVICE_LINKS) + 1, &stmt, NULL);
710     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
711
712     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
713     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
714
715     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
716     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
717
718     bool ret = false;
719     while(SQLITE_ROW == sqlite3_step(stmt))
720     {
721         OC_LOG(INFO, TAG, "Link already exists between devices");
722         ret = true;
723     }
724     sqlite3_finalize(stmt);
725     *result = ret;
726     return OC_STACK_OK;
727 }