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