File backups on seperate partition; Fixed bug 146; created performance benchmark...
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_key.c
1 /******************************************************************************
2  * Project         Persistency
3  * (c) copyright   2012
4  * Company         XS Embedded GmbH
5  *****************************************************************************/
6 /******************************************************************************
7  * This Source Code Form is subject to the terms of the
8  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed
9  * with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 ******************************************************************************/
11  /**
12  * @file           persistence_client_library_key.c
13  * @ingroup        Persistence client library
14  * @author         Ingo Huerner
15  * @brief          Implementation of the persistence client library.
16  *                 Library provides an API to access persistent data
17  * @see            
18  */
19
20 #include "persistence_client_library_key.h"
21
22 #include "../include_protected/persistence_client_library_db_access.h"
23 #include "../include_protected/persistence_client_library_rc_table.h"
24 #include "../include_protected/crc32.h"
25
26 #include "persistence_client_library_handle.h"
27 #include "persistence_client_library_pas_interface.h"
28 #include "persistence_client_library_prct_access.h"
29 #include "persistence_client_library_custom_loader.h"
30
31
32 // ----------------------------------------------------------------------------
33 // ----------------------------------------------------------------------------
34 // function with handle
35 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
37
38 int pclKeyHandleOpen(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no)
39 {
40    int handle = EPERS_NOT_INITIALIZED;
41
42    if(gPclInitialized >= PCLinitialized)
43    {
44       PersistenceInfo_s dbContext;
45
46       char dbKey[DbKeyMaxLen]   = {0};      // database key
47       char dbPath[DbPathMaxLen] = {0};    // database location
48
49       //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleOpen: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
50       dbContext.context.ldbid   = ldbid;
51       dbContext.context.seat_no = seat_no;
52       dbContext.context.user_no = user_no;
53
54       // get database context: database path and database key
55       handle = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
56       if(   (handle >= 0)
57          && (dbContext.configKey.type == PersistenceResourceType_key) )          // check if type matches
58       {
59          if(dbContext.configKey.storage < PersistenceStorage_LastEntry)    // check if store policy is valid
60          {
61             if(PersistenceStorage_custom ==  dbContext.configKey.storage)
62             {
63                int idx =  custom_client_name_to_id(dbPath, 1);
64                char workaroundPath[128];  // workaround, because /sys/ can not be accessed on host!!!!
65                snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath  );
66
67                if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_open != NULL) )
68                {
69                   int flag = 0, mode = 0;
70                   handle = gPersCustomFuncs[idx].custom_plugin_handle_open(workaroundPath, flag, mode);
71                }
72                else
73                {
74                   handle = EPERS_NOPLUGINFUNCT;
75                }
76             }
77             else
78             {
79                handle = get_persistence_handle_idx();
80             }
81
82             if((handle < MaxPersHandle) && (0 <= handle))
83             {
84                // remember data in handle array
85                strncpy(gKeyHandleArray[handle].dbPath, dbPath, DbPathMaxLen);
86                strncpy(gKeyHandleArray[handle].dbKey,  dbKey,  DbKeyMaxLen);
87                strncpy(gKeyHandleArray[handle].resourceID,  resource_id,  DbResIDMaxLen);
88                gKeyHandleArray[handle].dbPath[DbPathMaxLen-1] = '\0'; // Ensures 0-Termination
89                gKeyHandleArray[handle].dbKey[ DbPathMaxLen-1] = '\0'; // Ensures 0-Termination
90                gKeyHandleArray[handle].info = dbContext;
91             }
92             else
93             {
94                DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleOpen: error - handleId out of bounds:"), DLT_INT(handle));
95             }
96          }
97       }
98       else
99       {
100          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleOpen: error - no database context or resource is not a key "));
101       }
102    }
103
104
105    return handle;
106 }
107
108
109
110 int pclKeyHandleClose(int key_handle)
111 {
112    int rval = EPERS_NOT_INITIALIZED;
113
114    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleClose: "),
115    //                DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
116
117    if(gPclInitialized >= PCLinitialized)
118    {
119       if(key_handle < MaxPersHandle)
120       {
121          if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage )
122          {
123             int idx =  custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
124
125             if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_close != NULL) )
126             {
127                rval = gPersCustomFuncs[idx].custom_plugin_handle_close(key_handle);
128             }
129             else
130             {
131                rval = EPERS_NOPLUGINFUNCT;
132             }
133          }
134          else
135          {
136             set_persistence_handle_close_idx(key_handle);
137             rval = 1;
138          }
139
140          // invalidate entries
141          memset(gKeyHandleArray[key_handle].dbPath, 0, DbPathMaxLen);
142          memset(gKeyHandleArray[key_handle].dbKey  ,0, DbKeyMaxLen);
143          gKeyHandleArray[key_handle].info.configKey.storage = -1;
144       }
145       else
146       {
147          rval = EPERS_MAXHANDLE;
148       }
149    }
150
151    return rval;
152 }
153
154
155
156 int pclKeyHandleGetSize(int key_handle)
157 {
158    int size = EPERS_NOT_INITIALIZED;
159
160    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleGetSize: "),
161    //                DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
162
163    if(gPclInitialized >= PCLinitialized)
164    {
165       if(key_handle < MaxPersHandle)
166       {
167          if(PersistenceStorage_custom ==  gKeyHandleArray[key_handle].info.configKey.storage)
168          {
169             int idx =  custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
170
171             if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_size != NULL) )
172             {
173                size = gPersCustomFuncs[idx].custom_plugin_get_size(gKeyHandleArray[key_handle].dbPath);
174             }
175             else
176             {
177                size = EPERS_NOPLUGINFUNCT;
178             }
179          }
180          else
181          {
182             size = pers_db_get_key_size(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey,
183                                              &gKeyHandleArray[key_handle].info);
184          }
185       }
186       else
187       {
188          size = EPERS_MAXHANDLE;
189       }
190    }
191
192    return size;
193 }
194
195
196
197 int pclKeyHandleReadData(int key_handle, unsigned char* buffer, int buffer_size)
198 {
199    int size = EPERS_NOT_INITIALIZED;
200
201    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleReadData: "),
202    //             DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
203
204    if(gPclInitialized >= PCLinitialized)
205    {
206       if(key_handle < MaxPersHandle)
207       {
208          if(PersistenceStorage_custom ==  gKeyHandleArray[key_handle].info.configKey.storage)
209          {
210             int idx =  custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
211
212             if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_get_data != NULL) )
213             {
214                size = gPersCustomFuncs[idx].custom_plugin_handle_get_data(key_handle, (char*)buffer, buffer_size-1);
215             }
216             else
217             {
218                size = EPERS_NOPLUGINFUNCT;
219             }
220          }
221          else
222          {
223             size = pers_db_read_key(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey,
224                                         &gKeyHandleArray[key_handle].info, buffer, buffer_size);
225          }
226       }
227       else
228       {
229          size = EPERS_MAXHANDLE;
230       }
231    }
232
233    return size;
234 }
235
236
237
238 int pclKeyHandleRegisterNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback)
239 {
240    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleRegisterNotifyOnChange: "),
241    //            DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
242
243    return handleRegNotifyOnChange(key_handle, callback, Notify_register);
244 }
245
246 int pclKeyHandleUnRegisterNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback)
247 {
248    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleUnRegisterNotifyOnChange: "),
249    //         DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
250
251    return handleRegNotifyOnChange(key_handle, callback, Notify_unregister);
252 }
253
254
255
256 int handleRegNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
257 {
258    int rval = EPERS_NOT_INITIALIZED;
259
260    if(gPclInitialized >= PCLinitialized)
261    {
262       if(key_handle < MaxPersHandle)
263       {
264          rval = regNotifyOnChange(gKeyHandleArray[key_handle].info.context.ldbid,
265                                   gKeyHandleArray[key_handle].resourceID,
266                                   gKeyHandleArray[key_handle].info.context.user_no,
267                                   gKeyHandleArray[key_handle].info.context.seat_no,
268                                   callback,
269                                   regPolicy);
270       }
271       else
272       {
273          rval = EPERS_MAXHANDLE;
274       }
275    }
276    return rval;
277 }
278
279
280
281 int pclKeyHandleWriteData(int key_handle, unsigned char* buffer, int buffer_size)
282 {
283    int size = EPERS_NOT_INITIALIZED;
284
285    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleWriteData: "),
286    //                DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
287
288    if(gPclInitialized >= PCLinitialized)
289    {
290       if(AccessNoLock != isAccessLocked() )     // check if access to persistent data is locked
291       {
292          if(buffer_size <= gMaxKeyValDataSize)  // check data size
293          {
294             if(key_handle < MaxPersHandle)
295             {
296                if(gKeyHandleArray[key_handle].info.configKey.permission != PersistencePermission_ReadOnly)  // don't write to a read only resource
297                {
298                   if(PersistenceStorage_custom ==  gKeyHandleArray[key_handle].info.configKey.storage)
299                   {
300                      int idx =  custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
301
302                      if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data != NULL) )
303                      {
304                         size = gPersCustomFuncs[idx].custom_plugin_handle_set_data(key_handle, (char*)buffer, buffer_size-1);
305
306                         if(size >= 0) // success ==> send change notification
307                         {
308                            int rval = pers_send_Notification_Signal(gKeyHandleArray[key_handle].dbKey,
309                                                                   &(gKeyHandleArray[key_handle].info.context), pclNotifyStatus_changed);
310
311                            if(rval <= 0)
312                            {
313                               DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleWriteData: error - failed to send notification"));
314                               size = rval;
315                            }
316                         }
317                      }
318                      else
319                      {
320                         size = EPERS_NOPLUGINFUNCT;
321                      }
322                   }
323                   else
324                   {
325                      size = pers_db_write_key(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey,
326                                               &gKeyHandleArray[key_handle].info, buffer, buffer_size);
327                   }
328                }
329                else
330                {
331                   size = EPERS_RESOURCE_READ_ONLY;
332                }
333
334             }
335             else
336             {
337                size = EPERS_MAXHANDLE;
338             }
339          }
340          else
341          {
342             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleWriteData: error - buffer_size to big, limit is [bytes]:"), DLT_INT(gMaxKeyValDataSize));
343             size = EPERS_MAX_BUFF_SIZE;
344          }
345       }
346       else
347       {
348          size = EPERS_LOCKFS;
349       }
350    }
351
352    return size;
353 }
354
355
356
357
358
359 // ----------------------------------------------------------------------------
360 // ----------------------------------------------------------------------------
361 // functions to be used directly without a handle
362 // ----------------------------------------------------------------------------
363 // ----------------------------------------------------------------------------
364
365 int pclKeyDelete(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no)
366 {
367    int rval = EPERS_NOT_INITIALIZED;
368
369    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyDelete: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
370
371    if(gPclInitialized >= PCLinitialized)
372    {
373       if(AccessNoLock != isAccessLocked() ) // check if access to persistent data is locked
374       {
375          PersistenceInfo_s dbContext;
376
377         char dbKey[DbKeyMaxLen]   = {0};      // database key
378         char dbPath[DbPathMaxLen] = {0};    // database location
379
380         dbContext.context.ldbid   = ldbid;
381         dbContext.context.seat_no = seat_no;
382         dbContext.context.user_no = user_no;
383
384         // get database context: database path and database key
385         rval = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
386         if(   (rval >= 0)
387            && (dbContext.configKey.type == PersistenceResourceType_key) )  // check if type is matching
388         {
389            if(   dbContext.configKey.storage < PersistenceStorage_LastEntry
390               && dbContext.configKey.storage >= PersistenceStorage_local)   // check if store policy is valid
391            {
392               rval = pers_db_delete_key(dbPath, dbKey, &dbContext);
393            }
394            else
395            {
396              rval = EPERS_BADPOL;
397            }
398         }
399       }
400       else
401       {
402          rval = EPERS_LOCKFS;
403       }
404    }
405
406    return rval;
407 }
408
409
410
411 // status: OK
412 int pclKeyGetSize(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no)
413 {
414    int data_size = EPERS_NOT_INITIALIZED;
415
416    if(gPclInitialized >= PCLinitialized)
417    {
418       PersistenceInfo_s dbContext;
419
420       char dbKey[DbKeyMaxLen]   = {0};      // database key
421       char dbPath[DbPathMaxLen] = {0};    // database location
422
423       dbContext.context.ldbid   = ldbid;
424       dbContext.context.seat_no = seat_no;
425       dbContext.context.user_no = user_no;
426
427       //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyGetSize: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
428
429       // get database context: database path and database key
430       data_size = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
431       if(   (data_size >= 0)
432          && (dbContext.configKey.type == PersistenceResourceType_key) )    // check if type matches
433       {
434          if(   dbContext.configKey.storage < PersistenceStorage_LastEntry
435             && dbContext.configKey.storage >= PersistenceStorage_local)   // check if store policy is valid
436          {
437             data_size = pers_db_get_key_size(dbPath, dbKey, &dbContext);
438          }
439          else
440          {
441            data_size = EPERS_BADPOL;
442          }
443       }
444       else
445       {
446         data_size = EPERS_BADPOL;
447       }
448    }
449
450    return data_size;
451 }
452
453
454
455 // status: OK
456 int pclKeyReadData(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no,
457                   unsigned char* buffer, int buffer_size)
458 {
459    int data_size = EPERS_NOT_INITIALIZED;
460
461    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyReadData: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
462
463    if(gPclInitialized >= PCLinitialized)
464    {
465       if(AccessNoLock != isAccessLocked() ) // check if access to persistent data is locked
466       {
467          PersistenceInfo_s dbContext;
468
469          char dbKey[DbKeyMaxLen]   = {0};      // database key
470          char dbPath[DbPathMaxLen] = {0};    // database location
471
472          dbContext.context.ldbid   = ldbid;
473          dbContext.context.seat_no = seat_no;
474          dbContext.context.user_no = user_no;
475
476          // get database context: database path and database key
477          data_size = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
478          if(   (data_size >= 0)
479             && (dbContext.configKey.type == PersistenceResourceType_key) )
480          {
481
482             if(   dbContext.configKey.storage <  PersistenceStorage_LastEntry
483                && dbContext.configKey.storage >= PersistenceStorage_local)   // check if store policy is valid
484             {
485                   data_size = pers_db_read_key(dbPath, dbKey, &dbContext, buffer, buffer_size);
486             }
487             else
488             {
489                data_size = EPERS_BADPOL;
490             }
491          }
492          else
493          {
494             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyReadData - error - no database context or resource is not a key"));
495          }
496       }
497       else
498       {
499          data_size = EPERS_LOCKFS;
500       }
501    }
502
503    return data_size;
504 }
505
506
507
508 int pclKeyWriteData(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no,
509                    unsigned char* buffer, int buffer_size)
510 {
511    int data_size = EPERS_NOT_INITIALIZED;
512
513    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyWriteData: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
514
515    if(gPclInitialized >= PCLinitialized)
516    {
517       if(AccessNoLock != isAccessLocked() )     // check if access to persistent data is locked
518       {
519          if(buffer_size <= gMaxKeyValDataSize)  // check data size
520          {
521             PersistenceInfo_s dbContext;
522
523             unsigned int hash_val_data = 0;
524
525             char dbKey[DbKeyMaxLen]   = {0};      // database key
526             char dbPath[DbPathMaxLen] = {0};    // database location
527
528             dbContext.context.ldbid   = ldbid;
529             dbContext.context.seat_no = seat_no;
530             dbContext.context.user_no = user_no;
531
532             // get database context: database path and database key
533             data_size = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
534             if(   (data_size >= 0)
535                && (dbContext.configKey.type == PersistenceResourceType_key))
536             {
537                if(dbContext.configKey.permission != PersistencePermission_ReadOnly)  // don't write to a read only resource
538                {
539                   // get hash value of data to verify storing
540                   hash_val_data = pclCrc32(hash_val_data, buffer, buffer_size);
541
542                   // store data
543                   if(   dbContext.configKey.storage <  PersistenceStorage_LastEntry
544                      && dbContext.configKey.storage >= PersistenceStorage_local)   // check if store policy is valid
545                   {
546                      data_size = pers_db_write_key(dbPath, dbKey, &dbContext, buffer, buffer_size);
547                   }
548                   else
549                   {
550                      data_size = EPERS_BADPOL;
551                   }
552                }
553                else
554                {
555                   data_size = EPERS_RESOURCE_READ_ONLY;
556                }
557             }
558             else
559             {
560                DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyWriteData - error - no database context or resource is not a key"));
561             }
562          }
563          else
564          {
565             data_size = EPERS_BUFLIMIT;
566             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyWriteData: error - buffer_size to big, limit is [bytes]:"), DLT_INT(gMaxKeyValDataSize));
567          }
568       }
569       else
570       {
571          data_size = EPERS_LOCKFS;
572       }
573    }
574
575    return data_size;
576 }
577
578
579
580 int pclKeyUnRegisterNotifyOnChange( unsigned int  ldbid, const char *  resource_id, unsigned int  user_no, unsigned int  seat_no, pclChangeNotifyCallback_t  callback)
581 {
582    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyUnRegisterNotifyOnChange: "),
583    //            DLT_INT(ldbid), DLT_STRING(resource_id) );
584
585    return regNotifyOnChange(ldbid, resource_id, user_no, seat_no, callback, Notify_unregister);
586 }
587
588
589 int pclKeyRegisterNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, pclChangeNotifyCallback_t callback)
590 {
591    //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyRegisterNotifyOnChange: "),
592    //            DLT_INT(ldbid), DLT_STRING(resource_id) );
593
594    return regNotifyOnChange(ldbid, resource_id, user_no, seat_no, callback, Notify_register);
595 }
596
597
598
599
600 int regNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
601 {
602    int rval = EPERS_NOT_INITIALIZED;
603
604    if(gPclInitialized >= PCLinitialized)
605    {
606       PersistenceInfo_s dbContext;
607
608       //   unsigned int hash_val_data = 0;
609       char dbKey[DbKeyMaxLen]   = {0};      // database key
610       char dbPath[DbPathMaxLen] = {0};    // database location
611
612       //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyRegisterNotifyOnChange: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
613
614       dbContext.context.ldbid   = ldbid;
615       dbContext.context.seat_no = seat_no;
616       dbContext.context.user_no = user_no;
617
618       // get database context: database path and database key
619       rval = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
620
621       // registration is only on shared and custom keys possible
622       if(   (dbContext.configKey.storage != PersistenceStorage_local)
623         && (dbContext.configKey.type    == PersistenceResourceType_key) )
624       {
625          rval = persistence_notify_on_change(dbKey, ldbid, user_no, seat_no, callback, regPolicy);
626       }
627       else
628       {
629          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyRegisterNotifyOnChange: error - resource is not a shared resource or resource is not a key"));
630          rval = EPERS_NOTIFY_NOT_ALLOWED;
631       }
632    }
633
634    return rval;
635 }
636
637
638
639
640
641
642