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