Check PDM Initialization before excuting exposed PDM 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 #include <stdio.h>
22 #include <stdbool.h>
23 #include <sqlite3.h>
24 #include <string.h>
25 #include <stdlib.h>
26
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
77 #define ASCENDING_ORDER(id1, id2) do{if( (id1) > (id2) )\
78   { int temp; temp = id1; id1 = id2; id2 = temp; }}while(0)
79
80 #define CHECK_PDM_INIT(tag) do{if(true != gInit)\
81   { OC_LOG(ERROR, (tag), PCF("PDB is not initialized")); \
82     return OC_STACK_PDM_IS_NOT_INITIALIZED; }}while(0)
83
84 static sqlite3 *g_db = NULL;
85 static bool gInit = false;  /* Only if we can open sqlite db successfully, gInit is true. */
86
87 /**
88  * function to create DB in case DB doesn't exists
89  */
90 static OCStackResult createDB(const char* path)
91 {
92
93     int result = 0;
94     result = sqlite3_open_v2(path, &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
95     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
96
97     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LIST, NULL, NULL, NULL);
98     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
99
100     OC_LOG(INFO, TAG, "Created T_DEVICE_LIST");
101     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LINK, NULL, NULL, NULL);
102     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
103
104     OC_LOG(INFO, TAG, "Created T_DEVICE_LINK_STATE");
105     gInit = true;
106     return OC_STACK_OK;
107 }
108
109
110 /**
111  * Function to begin any transaction
112  */
113 static OCStackResult begin()
114 {
115     int res = 0;
116     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_BEGIN, NULL, NULL, NULL);
117     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
118     return OC_STACK_OK;
119 }
120
121 /**
122  * Function to commit any transaction
123  */
124 static OCStackResult commit()
125 {
126     int res = 0;
127     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_COMMIT, NULL, NULL, NULL);
128     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
129     return OC_STACK_OK;
130 }
131
132 /**
133  * Function to rollback any transaction
134  */
135 static OCStackResult rollback()
136 {
137     int res = 0;
138     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_ROLLBACK, NULL, NULL, NULL);
139     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
140     return OC_STACK_OK;
141 }
142
143 /**
144  * Error log callback called by SQLite stack in case of error
145  */
146 void errLogCallback(void *pArg, int iErrCode, const char *zMsg)
147 {
148     (void) pArg;
149     (void) iErrCode;
150     (void) zMsg;
151     OC_LOG_V(DEBUG,TAG, "(%d) %s", iErrCode, zMsg);
152 }
153
154 OCStackResult PDMInit(const char *path)
155 {
156     int rc;
157     const char *dbPath = NULL;
158     if (SQLITE_OK !=  sqlite3_config(SQLITE_CONFIG_LOG, errLogCallback, NULL))
159     {
160         OC_LOG(INFO, TAG, "Unable to enable debug log of sqlite");
161     }
162
163     if (NULL == path || !*path)
164     {
165         dbPath = DB_FILE;
166     }
167     else
168     {
169         dbPath = path;
170     }
171     rc = sqlite3_open_v2(dbPath, &g_db, SQLITE_OPEN_READWRITE, NULL);
172     if (SQLITE_OK != rc)
173     {
174         OC_LOG_V(INFO, TAG, "ERROR: Can't open database: %s", sqlite3_errmsg(g_db));
175         return createDB(dbPath);
176     }
177     gInit = true;
178     return OC_STACK_OK;
179 }
180
181
182 OCStackResult PDMAddDevice(const OicUuid_t *UUID)
183 {
184     CHECK_PDM_INIT(TAG);
185     if (NULL == UUID)
186     {
187         return OC_STACK_INVALID_PARAM;
188     }
189
190     sqlite3_stmt *stmt = 0;
191     int res =0;
192     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_T_DEVICE_LIST,
193                               strlen(PDM_SQLITE_INSERT_T_DEVICE_LIST) + 1, &stmt, NULL);
194     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
195
196     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
197     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
198
199     res = sqlite3_step(stmt);
200     if (SQLITE_DONE != res)
201     {
202         if (SQLITE_CONSTRAINT == res)
203         {
204             //new OCStack result code
205             OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
206             sqlite3_finalize(stmt);
207             return OC_STACK_DUPLICATE_UUID;
208         }
209         OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
210         sqlite3_finalize(stmt);
211         return OC_STACK_ERROR;
212     }
213     sqlite3_finalize(stmt);
214     return OC_STACK_OK;
215 }
216
217 /**
218  *function to get Id for given UUID
219  */
220 static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
221 {
222     sqlite3_stmt *stmt = 0;
223     int res = 0;
224     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
225     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
226
227     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
228     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
229
230     OC_LOG(DEBUG, TAG, "Binding Done");
231     while (SQLITE_ROW == sqlite3_step(stmt))
232     {
233         int tempId = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
234         OC_LOG_V(DEBUG, TAG, "ID is %d", tempId);
235         *id = tempId;
236     }
237     sqlite3_finalize(stmt);
238     return OC_STACK_OK;
239 }
240
241 /**
242  * Function to check duplication of device's Device ID.
243  */
244 bool PDMIsDuplicateDevice(const OicUuid_t* UUID)
245 {
246     if(gInit)
247     {
248         if (NULL == UUID)
249         {
250             OC_LOG(ERROR, TAG, "UUID is NULL");
251             return true;
252         }
253
254         sqlite3_stmt *stmt = 0;
255         int res = 0;
256         res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
257         PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
258
259         res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
260         PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
261
262         OC_LOG(DEBUG, TAG, "Binding Done");
263
264         while (SQLITE_ROW == sqlite3_step(stmt))
265         {
266             OC_LOG(ERROR, TAG, "UUID is duplicated");
267             sqlite3_finalize(stmt);
268             return true;
269         }
270         sqlite3_finalize(stmt);
271         return false;
272     }
273     OC_LOG(ERROR, TAG, PCF("PDB is not initialized"));
274     return true; // return true will stop futher process.
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_OK;
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 OCStackResult PDMDestoryOicUuidLinkList(OCUuidList_t* ptr)
657 {
658     OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
659     LL_FOREACH_SAFE(ptr, tmp1, tmp2)
660     {
661         LL_DELETE(ptr, tmp1);
662         OICFree(tmp1);
663     }
664     return OC_STACK_OK;
665 }
666
667 OCStackResult PDMDestoryStaleLinkList(OCPairList_t* ptr)
668 {
669     OCPairList_t *tmp1 = NULL,*tmp2=NULL;
670     LL_FOREACH_SAFE(ptr, tmp1, tmp2)
671     {
672         LL_DELETE(ptr, tmp1);
673         OICFree(tmp1);
674     }
675     return OC_STACK_OK;
676 }