Init basesystem source codes.
[staging/basesystem.git] / nsframework / notification_persistent_service / server / src / ns_npp_nor_persistence_worker_thread.cpp
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 ////////////////////////////////////////////////////////////////////////////////////////////////////
18 /// \defgroup <<Group Tag>> <<Group Name>>
19 /// \ingroup  tag_NS_NPPService
20 /// .
21 ////////////////////////////////////////////////////////////////////////////////////////////////////
22
23 ////////////////////////////////////////////////////////////////////////////////////////////////////
24 /// \ingroup  tag_NS_NPPService
25 /// \brief    This file contain declaration of class CNorPersistenceWorker and CArchive.
26 ///       Class CNorPersistenceWorker holds the implementation for worker thread.
27 ///       Class CArchive holds the implementation for archive.
28 ///
29 ////////////////////////////////////////////////////////////////////////////////////////////////////
30
31 #include <native_service/ns_timer_if.hpp>
32 #include <native_service/ns_np_service_if.h>
33 #include <native_service/ns_utility_sys.hpp>
34 #include <native_service/frameworkunified_framework_if.h>
35 #include <native_service/frameworkunified_multithreading.h>
36 #include <native_service/frameworkunified_service_protocol.h>
37 #include <native_service/ns_np_service_protocol.h>
38 #include <native_service/ns_np_service_nor_persistence.h>
39
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <boost/bind.hpp>
44 #include <map>
45 #include <utility>
46 #include <string>
47
48 #include <native_service/ns_np_service_nor_persistence_internal.h>
49 #include "ns_npp_types.h"
50 #include "ns_npp_notificationpersistentservicelog.h"
51 #include "ns_npp_fs_directory.h"
52 #include "ns_npp_persistent_data.h"
53 #include "ns_npp_nor_persistence_worker_thread.h"
54
55
56
57 typedef std::string NotificationName;
58 typedef std::map<NotificationName, CTimerHelper *> TTimerList;
59 static TTimerList g_mtimers;  /// List of all the timers for immediate persistence notifications
60 CMutex g_objmutextimerdata;  /// Mutex object on g_mtimers
61
62 // Template function for NorWorkerCallback
63 template <typename C, eFrameworkunifiedStatus(C::*M)(HANDLE)> EFrameworkunifiedStatus NorWorkerCallback(HANDLE hthread) {
64   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
65
66   C *l_pClass = static_cast<C *>(FrameworkunifiedGetThreadSpecificData(hthread));
67
68   if (l_pClass) {  // LCOV_EXCL_BR_LINE 6: l_pClass can't be NULL
69     l_estatus = (l_pClass->*M)(hthread);
70   }
71   return l_estatus;
72 }
73
74 static FrameworkunifiedProtocolCallbackHandler aServiceHandlers[] = {  // NOLINT (readability/naming)
75   { NOR_PERSISTENCE_TIMER_START,      NorWorkerCallback<CNorPersistenceWorker,
76     &CNorPersistenceWorker::OnNorPersistenceTimerStart>},
77   { NOR_PERSISTENCE_REGISTER,       NorWorkerCallback<CNorPersistenceWorker,
78     &CNorPersistenceWorker::RegisterImmediatePersistNotification>},
79   { NOR_PERSISTENCE_UNREGISTER,     NorWorkerCallback<CNorPersistenceWorker,
80     &CNorPersistenceWorker::UnregisterImmediatePersistNotification>},
81   { NOR_PERSISTENCE_ONSHUTDOWN,       NorWorkerCallback<CNorPersistenceWorker,
82     &CNorPersistenceWorker::OnShutdown>},
83   { NOR_PERSISTENCE_CHANGE_CATEGORY,  NorWorkerCallback<CNorPersistenceWorker,
84     &CNorPersistenceWorker::OnCategoryChange>}
85 };
86
87 ////////////////////////////////////////////////////////////////////////////////////////////////////
88 /// NSPNorPersistenceWorkerOnStart
89 /// Callback method on start of worker thread
90 ////////////////////////////////////////////////////////////////////////////////////////////////////
91 EFrameworkunifiedStatus NSPNorPersistenceWorkerOnStart(HANDLE hthread) {
92   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
93   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
94
95   if (NULL != hthread) {  // LCOV_EXCL_BR_LINE 6: hthread can't be NULL
96     // Note: this variable is made static just to ignore the resource leak showing in coverity analysis
97     static CNorPersistenceWorker *l_pcnorpersistenceworker = new(std::nothrow) CNorPersistenceWorker;
98
99     if (NULL != l_pcnorpersistenceworker) {  // LCOV_EXCL_BR_LINE 5: new's error case
100       l_estatus = FrameworkunifiedSetThreadSpecificData(hthread, l_pcnorpersistenceworker);
101
102       if (eFrameworkunifiedStatusOK == l_estatus) {  // LCOV_EXCL_BR_LINE 4: NSFW error case
103         l_estatus = FrameworkunifiedAttachCallbacksToDispatcher(
104                       hthread, AppName, aServiceHandlers, static_cast<UI_32>(_countof(aServiceHandlers)));
105       } else {
106         // LCOV_EXCL_START 4: NSFW error case
107         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
108         delete l_pcnorpersistenceworker;
109         l_pcnorpersistenceworker = NULL;
110         // LCOV_EXCL_STOP
111       }
112     } else {
113       // LCOV_EXCL_START 5: new's error case
114       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
115       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Worker Object Null.");
116       l_estatus = eFrameworkunifiedStatusNullPointer;
117       // LCOV_EXCL_STOP
118     }
119   } else {
120     // LCOV_EXCL_START 6: hthread can't be NULL
121     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
122     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Thread App Handle Null.");
123     l_estatus = eFrameworkunifiedStatusInvldHandle;
124     // LCOV_EXCL_STOP
125   }
126
127   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
128   return l_estatus;
129 }
130
131 ////////////////////////////////////////////////////////////////////////////////////////////////////
132 /// NSPNorPersistenceWorkerOnStop
133 /// Callback method on stop of worker thread
134 ////////////////////////////////////////////////////////////////////////////////////////////////////
135 EFrameworkunifiedStatus NSPNorPersistenceWorkerOnStop(HANDLE hthread) {  // LCOV_EXCL_START 200: can't test
136   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
137   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
138   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
139
140   if (NULL != hthread) {
141     CNorPersistenceWorker *l_pcnorpersistenceworker = static_cast<CNorPersistenceWorker *>(FrameworkunifiedGetThreadSpecificData(
142                                                                                              hthread));
143
144     if (NULL != l_pcnorpersistenceworker) {
145       delete l_pcnorpersistenceworker;
146       l_pcnorpersistenceworker = NULL;
147     } else {
148       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Worker Object Null");
149       l_estatus = eFrameworkunifiedStatusNullPointer;
150     }
151
152     if (eFrameworkunifiedStatusOK != (l_estatus = FrameworkunifiedSetThreadSpecificData(hthread, NULL))) {
153       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedSetThreadSpecificData error, status=%d", l_estatus);
154     }
155
156     PCSTR l_cservice = FrameworkunifiedGetAppName(hthread);
157     if (NULL != l_cservice) {
158       if (eFrameworkunifiedStatusOK != (l_estatus = FrameworkunifiedDetachServiceFromDispatcher(hthread, l_cservice))) {
159         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Error detaching service %s from dispatcher, status=%d", l_cservice, l_estatus);
160       }
161     } else {
162       l_estatus = eFrameworkunifiedStatusNullPointer;
163       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedGetAppName returned NULL");
164     }
165   } else {
166     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Thread App Handle Null.");
167     l_estatus = eFrameworkunifiedStatusInvldHandle;
168   }
169   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
170
171   return l_estatus;
172 }
173 // LCOV_EXCL_STOP
174
175 ////////////////////////////////////////////////////////////////////////////////////////////////////
176 /// Class : CNorPersistenceWorker
177 ////////////////////////////////////////////////////////////////////////////////////////////////////
178
179 ////////////////////////////////////////////////////////////////////////////////////////////////////
180 /// CNorPersistenceWorker
181 /// Constructor of CNorPersistenceWorker class
182 ////////////////////////////////////////////////////////////////////////////////////////////////////
183 CNorPersistenceWorker::CNorPersistenceWorker() {
184   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
185   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
186 }
187
188 ////////////////////////////////////////////////////////////////////////////////////////////////////
189 /// ~CNorPersistenceWorker
190 /// Destructor of CNorPersistenceWorker class
191 ////////////////////////////////////////////////////////////////////////////////////////////////////
192 CNorPersistenceWorker::~CNorPersistenceWorker() {
193   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
194   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
195 }
196
197 ////////////////////////////////////////////////////////////////////////////////////////////////////
198 /// OnNorPersistenceTimerStart
199 /// This function starts the respective timer of the notification.
200 ////////////////////////////////////////////////////////////////////////////////////////////////////
201 EFrameworkunifiedStatus CNorPersistenceWorker::OnNorPersistenceTimerStart(HANDLE f_hThread) {
202   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusFail;
203   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
204
205   TNorPersistenceNotifInfoHeader *l_ptNorPersistentData = NULL;
206   UI_32 l_ui32ReceivedDataLength = FrameworkunifiedGetMsgLength(f_hThread);
207   UI_8 *l_pui32ReceivedData = new(std::nothrow) UI_8[l_ui32ReceivedDataLength];
208
209   if (l_ui32ReceivedDataLength >= sizeof(TNorPersistenceNotifInfoHeader)) {  // LCOV_EXCL_BR_LINE 200: l_ui32ReceivedDataLength is bigger than sizeof(TNorPersistenceNotifInfoHeader)  // NOLINT[whitespace/line_length]
210     if (NULL != l_pui32ReceivedData) {  // LCOV_EXCL_BR_LINE 5: new's error case
211       std::memset(l_pui32ReceivedData, 0, l_ui32ReceivedDataLength);
212       l_estatus = FrameworkunifiedGetMsgDataOfSize(f_hThread, l_pui32ReceivedData, l_ui32ReceivedDataLength, eSMRRelease);
213       if (eFrameworkunifiedStatusOK == l_estatus) {  // LCOV_EXCL_BR_LINE 4: NSFW error case
214         TTimerList::iterator l_itTimerList;
215         l_ptNorPersistentData = static_cast<TNorPersistenceNotifInfoHeader *>(static_cast<PVOID>(l_pui32ReceivedData));
216
217         g_objmutextimerdata.WriteLock();
218         // find the corresponding timer object in the list of timers
219         l_itTimerList = g_mtimers.find(l_ptNorPersistentData->m_cnotificationname);
220         if (g_mtimers.end() != l_itTimerList) {  // LCOV_EXCL_BR_LINE 200: the notification must be registered
221           if (NULL != (l_itTimerList->second)) {  // LCOV_EXCL_BR_LINE 200: l_itTimerList->second can't be null
222             if (NULL != (l_itTimerList->second)->m_pui8HeaderAndData) {
223               delete[](l_itTimerList->second)->m_pui8HeaderAndData;
224               (l_itTimerList->second)->m_pui8HeaderAndData = NULL;
225             }
226
227             // Update specific immediate persistence notification data
228             (l_itTimerList->second)->m_pui8HeaderAndData = l_pui32ReceivedData;
229
230             // if corresponding timer is not already running start it.
231             if (!(l_itTimerList->second)->IsRunning()) {
232               (l_itTimerList->second)->Start();
233               FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Timer started, Notfn=%s", l_ptNorPersistentData->m_cnotificationname);
234             } else {
235               FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Timer already running for notfn %s. Data updated",
236                      l_ptNorPersistentData->m_cnotificationname);
237             }
238
239             l_estatus = eFrameworkunifiedStatusOK;
240           } else {
241             // LCOV_EXCL_START 200: l_itTimerList->second can't be null
242             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
243             l_estatus = eFrameworkunifiedStatusNullPointer;
244             FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Immediate persistence: Timer object NULL for Notfn:%s.",
245                    l_ptNorPersistentData->m_cnotificationname);
246             // LCOV_EXCL_STOP
247           }
248         } else {
249           // LCOV_EXCL_START 200: the notification must be registered
250           AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
251           l_estatus = eFrameworkunifiedStatusFail;
252           FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Immediate persistence notification not registered. Notification: %s ",
253                  l_ptNorPersistentData->m_cnotificationname != 0 ? l_ptNorPersistentData->m_cnotificationname : NULL);
254           // LCOV_EXCL_STOP
255         }
256         g_objmutextimerdata.Unlock();
257       } else {
258         // LCOV_EXCL_START 4: NSFW error case
259         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
260         l_estatus = eFrameworkunifiedStatusFail;
261         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
262                "FrameworkunifiedGetMsgDataOfSize failed while retrieving immediate persistence notfn data. Status:0x%x ", l_estatus);
263         // LCOV_EXCL_STOP
264       }
265     } else {
266       // LCOV_EXCL_START 5: new's error case
267       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
268       l_estatus = eFrameworkunifiedStatusNullPointer;
269       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Unable to allocate data. Can't persist.");
270       // LCOV_EXCL_STOP
271     }
272   } else {
273     // LCOV_EXCL_START 200: l_ui32ReceivedDataLength is bigger than sizeof(TNorPersistenceNotifInfoHeader)
274     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
275     l_estatus = eFrameworkunifiedStatusInvldBuf;
276     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Invalid data length received. Can't persist.");
277     // LCOV_EXCL_STOP
278   }
279
280   if ((eFrameworkunifiedStatusOK != l_estatus) && (NULL != l_pui32ReceivedData)) {
281     delete[] l_pui32ReceivedData;
282     l_pui32ReceivedData = NULL;
283   }
284
285   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
286   return l_estatus;
287 }
288
289 ////////////////////////////////////////////////////////////////////////////////////////////////////
290 /// RegisterImmediatePersistNotification
291 /// It creates a timer corresponding to the notification.
292 ////////////////////////////////////////////////////////////////////////////////////////////////////
293 EFrameworkunifiedStatus CNorPersistenceWorker::RegisterImmediatePersistNotification(HANDLE hthread) {
294   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
295   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
296
297   TImmediatePersistenceRegisterNotifInfo l_tRegisterNotifInfo = {};
298
299   if (sizeof(l_tRegisterNotifInfo) == FrameworkunifiedGetMsgLength(hthread)) {  // LCOV_EXCL_BR_LINE 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo)  // NOLINT[whitespace/line_length]
300     if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(hthread, &l_tRegisterNotifInfo,  // LCOV_EXCL_BR_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
301                                        sizeof(TImmediatePersistenceRegisterNotifInfo), eSMRRelease))) {
302       g_objmutextimerdata.WriteLock();
303
304       TTimerList::iterator l_itTimerList = g_mtimers.find(l_tRegisterNotifInfo.m_cnotificationname);
305       if (l_itTimerList != g_mtimers.end()) {  // LCOV_EXCL_BR_LINE 6: notification can't be registered again
306         // LCOV_EXCL_START 6: notification can't be registered again
307         FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Notification %s is already registered for immediate data persistence ",
308                l_tRegisterNotifInfo.m_cnotificationname);
309         // LCOV_EXCL_STOP
310       } else {
311         // create timer corresponding to notification
312         CTimerHelper *l_pTimerHelper = new CTimerHelper();
313         if (NULL != l_pTimerHelper) {  // LCOV_EXCL_BR_LINE 5: new's error case
314           l_pTimerHelper->SetTime(l_tRegisterNotifInfo.m_uidelay, 0);
315           // todo: modify SetNotifyMethod of timer NSTimer class to accept sender handle as well.
316           //       This will help to have only one handle, instead of one handle per timer.
317           l_pTimerHelper->SetNotifyMethod(static_cast<UI_16>(l_pTimerHelper->GetCmdId()), FrameworkunifiedGetAppName(hthread));
318
319           // associate timer's timeout with the callback function.
320           FrameworkunifiedAttachCallbackToDispatcher(hthread, TIMER_QUE, l_pTimerHelper->GetCmdId(),
321                                         boost::bind(&CTimerHelper::OnTimeOut, l_pTimerHelper, hthread));
322           // add created timer in timers list
323           g_mtimers.insert(std::make_pair(l_tRegisterNotifInfo.m_cnotificationname, l_pTimerHelper));
324           FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Notification %s is registered for immediate data persistence ",
325                  l_tRegisterNotifInfo.m_cnotificationname != 0 ? l_tRegisterNotifInfo.m_cnotificationname : NULL);
326         }
327       }
328
329       g_objmutextimerdata.Unlock();
330     } else {
331       // LCOV_EXCL_START 4: NSFW error case
332       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
333       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
334              "Error getting message data for registering Immediate persistent notification, status: 0x%x", l_estatus);
335       // LCOV_EXCL_STOP
336     }
337   } else {
338     // LCOV_EXCL_START 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo)
339     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
340     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
341            "FrameworkunifiedGetMsgLength and size of TImmediatePersistenceRegisterNotifInfo mismatched."
342            "Length received %d, buffer available: %ld ",
343            FrameworkunifiedGetMsgLength(hthread), static_cast<long int>(sizeof(TImmediatePersistenceRegisterNotifInfo))); // NOLINT (runtime/int)
344     // LCOV_EXCL_STOP
345   }
346
347   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
348   return l_estatus;
349 }
350
351 ////////////////////////////////////////////////////////////////////////////////////////////////////
352 /// UnregisterImmediatePersistNotification
353 /// It deletes a timer corresponding to the notification.
354 ////////////////////////////////////////////////////////////////////////////////////////////////////
355 EFrameworkunifiedStatus CNorPersistenceWorker::UnregisterImmediatePersistNotification(HANDLE hthread) {
356   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
357   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
358
359   TImmediatePersistenceUnregisterNotifInfo l_tRegisterNotifInfo = {};
360
361   if (sizeof(l_tRegisterNotifInfo) == FrameworkunifiedGetMsgLength(hthread)) {  // LCOV_EXCL_BR_LINE 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo)  // NOLINT[whitespace/line_length]
362     if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(hthread, &l_tRegisterNotifInfo,  // LCOV_EXCL_BR_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
363                                                     sizeof(TImmediatePersistenceUnregisterNotifInfo), eSMRRelease))) {
364       g_objmutextimerdata.WriteLock();
365
366       TTimerList::iterator l_itTimerList = g_mtimers.find(l_tRegisterNotifInfo.m_cnotificationname);
367       if (l_itTimerList != g_mtimers.end()) {  // LCOV_EXCL_BR_LINE 6: notification can't be unregistered again
368         if (NULL != (l_itTimerList->second)) {  // LCOV_EXCL_BR_LINE 200: l_itTimerList->second can't be null
369           EFrameworkunifiedStatus eStatus;
370           // detach callbacks
371           if (eFrameworkunifiedStatusOK != (eStatus = FrameworkunifiedDetachCallbackFromDispatcher(hthread, TIMER_QUE,  // LCOV_EXCL_BR_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
372                                                                          (l_itTimerList->second)->GetCmdId()))) {
373             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
374             FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Error: FrameworkunifiedDetachCallbackFromDispatcher Failed Status:0x%x ", eStatus);  // LCOV_EXCL_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
375           }
376           delete l_itTimerList->second;
377           l_itTimerList->second = NULL;
378         }
379         g_mtimers.erase(l_itTimerList);
380       } else {
381         // LCOV_EXCL_START 6: notification can't be registered again
382         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
383         FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__,
384                "Can't unregister. Notification %s is not a registered notification for immediate data persistence.",
385                l_tRegisterNotifInfo.m_cnotificationname != 0 ? l_tRegisterNotifInfo.m_cnotificationname : NULL);
386         // LCOV_EXCL_STOP
387       }
388
389       g_objmutextimerdata.Unlock();
390       FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__,
391              "Notification %s is unregistered for immediate data persistence, FrameworkunifiedGetMsgDataOfSize Error, status: 0x%x",
392              l_tRegisterNotifInfo.m_cnotificationname != 0 ? l_tRegisterNotifInfo.m_cnotificationname : NULL,
393              l_estatus);
394     }
395   } else {
396     // LCOV_EXCL_START 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo)
397     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
398     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
399            "FrameworkunifiedGetMsgLength and size of TImmediatePersistenceUnregisterNotifInfo mismatched."
400            "Length received %d, buffer available: %ld ",
401            FrameworkunifiedGetMsgLength(hthread), static_cast<long int>(sizeof(TImmediatePersistenceUnregisterNotifInfo))); // NOLINT (runtime/int)
402     // LCOV_EXCL_STOP
403   }
404
405   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
406   return l_estatus;
407 }
408
409 ////////////////////////////////////////////////////////////////////////////////////////////////////
410 /// OnShutdown
411 /// This API saves or deletes the data of NOR irrespective of delay depending on the message data
412 /// received from parent thread during shutdown.
413 ////////////////////////////////////////////////////////////////////////////////////////////////////
414 EFrameworkunifiedStatus CNorPersistenceWorker::OnShutdown(HANDLE f_hThread) {
415   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
416   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
417
418   UI_32 l_uiPersistCategoryFlag = 0;
419
420   TImmediateShutdown l_tImmShutdown = {};
421
422   CTimerHelper *l_pTimerHelper = NULL;
423
424   // iterator of list of nor notifications and its timers
425   TTimerList::iterator l_itTimerList;
426
427   TNorPersistenceNotifInfoHeader *l_ptImmediateNotfnHeader = NULL;
428
429   if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(f_hThread, &l_tImmShutdown, sizeof(l_tImmShutdown),  // LCOV_EXCL_BR_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
430                                                        eSMRRelease))) {
431     l_uiPersistCategoryFlag = l_tImmShutdown.f_uinotificationpersistentservicepersistcategoryflag;
432
433     // if quick shutdown is received then just stop the timer and dont save the data
434     if (eFrameworkunifiedQuickShutdown == l_tImmShutdown.f_eshutdowntype) {
435       for (l_itTimerList = g_mtimers.begin(); l_itTimerList != g_mtimers.end(); l_itTimerList++) {
436         l_pTimerHelper = l_itTimerList->second;
437
438         if (NULL != l_pTimerHelper && l_pTimerHelper->IsRunning()) {
439           // stop the timer
440           l_pTimerHelper->Stop();
441         }
442       }
443     } else {  // stop the timer and save the data
444       for (l_itTimerList = g_mtimers.begin(); l_itTimerList != g_mtimers.end(); l_itTimerList++) {
445         l_pTimerHelper = l_itTimerList->second;
446
447         if (NULL != l_pTimerHelper && l_pTimerHelper->IsRunning()) {
448           // stop the timer
449           l_pTimerHelper->Stop();
450
451           l_ptImmediateNotfnHeader = static_cast<TNorPersistenceNotifInfoHeader *>
452                   (static_cast<PVOID>(l_pTimerHelper->m_pui8HeaderAndData));
453
454           if (NULL != l_ptImmediateNotfnHeader) {  // LCOV_EXCL_BR_LINE 200: l_ptImmediateNotfnHeader can't be null
455             if (eFrameworkunifiedUserData       != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag) &&
456                 eFrameworkunifiedFactoryData      != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag) &&
457                 eFrameworkunifiedFactoryCustomerData  != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag) &&
458                 eFrameworkunifiedDealerData     != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag)) {
459               // save the new data to persistent memory
460               l_pTimerHelper->OnTimeOut(f_hThread);
461             }
462           } else {
463             // LCOV_EXCL_START 200: l_ptImmediateNotfnHeader can't be null
464             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
465             FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Immediate notification data header is NULL");
466             l_estatus = eFrameworkunifiedStatusFail;
467             // LCOV_EXCL_STOP
468           }
469         }
470       }
471     }
472   } else {
473     // LCOV_EXCL_START 4: NSFW error case
474     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
475     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedGetMsgDataOfSize failed for protocol NOR_PERSISTENCE_ONSHUTDOWN, status : %d",
476            l_estatus);
477     // LCOV_EXCL_STOP
478   }
479
480   if (eFrameworkunifiedStatusOK != (l_estatus = FrameworkunifiedSendParent(f_hThread, NOR_PERSISTENCE_ONSHUTDOWN_ACK,  // LCOV_EXCL_BR_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
481                                                  sizeof(l_uiPersistCategoryFlag), &l_uiPersistCategoryFlag))) {
482     // LCOV_EXCL_START 4: NSFW error case
483     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
484     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedSendParent failed for protocol NOR_PERSISTENCE_ONSHUTDOWN_ACK, status : %d",
485            l_estatus);
486     // LCOV_EXCL_STOP
487   }
488
489   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
490   return l_estatus;
491 }
492
493 ////////////////////////////////////////////////////////////////////////////////////////////////////
494 /// OnCategoryChange
495 /// This callback is called when category of immediate persistence is changed
496 ////////////////////////////////////////////////////////////////////////////////////////////////////
497 EFrameworkunifiedStatus CNorPersistenceWorker::OnCategoryChange(HANDLE hthread) {
498   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
499   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
500
501   if (NULL != hthread) {  // LCOV_EXCL_BR_LINE 4: NSFW error case
502     UI_32 l_ui32ReceivedDataLength = FrameworkunifiedGetMsgLength(hthread);
503
504     if (l_ui32ReceivedDataLength >= sizeof(TImmediatePersistenceChangeCategory)) {  // LCOV_EXCL_BR_LINE 200: l_ui32ReceivedDataLength is bigger than sizeof(TImmediatePersistenceChangeCategory)  // NOLINT[whitespace/line_length]
505       UI_8 *l_pui32ReceivedData = new(std::nothrow) UI_8[l_ui32ReceivedDataLength];
506
507       if (NULL != l_pui32ReceivedData) {  // LCOV_EXCL_BR_LINE 5: new's error case
508         std::memset(l_pui32ReceivedData, 0, l_ui32ReceivedDataLength);
509         if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(hthread, l_pui32ReceivedData, l_ui32ReceivedDataLength,  // LCOV_EXCL_BR_LINE 4: NSFW error case  // NOLINT[whitespace/line_length]
510                                                              eSMRRelease))) {
511           TImmediatePersistenceChangeCategory *l_pChangePersistentCategory =
512                   static_cast<TImmediatePersistenceChangeCategory *>(static_cast<PVOID>(l_pui32ReceivedData));
513           PUI_8 l_pui8Data = l_pui32ReceivedData + sizeof(TImmediatePersistenceChangeCategory);
514
515           TTimerList::iterator l_itTimerList;
516
517           g_objmutextimerdata.WriteLock();
518           // find the corresponding timer object in the list of timers
519           l_itTimerList = g_mtimers.find(l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname);
520           if (g_mtimers.end() != l_itTimerList) {  // LCOV_EXCL_BR_LINE 6: notification must be in list
521             CTimerHelper *l_pTimerHelper = l_itTimerList->second;
522
523             if (NULL != l_pTimerHelper && l_pTimerHelper->IsRunning()) {
524               TNorPersistenceNotifInfoHeader *l_ptImmediateNotfnHeader =
525                 static_cast<TNorPersistenceNotifInfoHeader *>(static_cast<PVOID>(l_pTimerHelper->m_pui8HeaderAndData));
526
527               if (NULL != l_ptImmediateNotfnHeader) {  // LCOV_EXCL_BR_LINE 200: l_ptImmediateNotfnHeader can't be null
528                 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Changing category from %d to %d for notfn %s in dataHdr",
529                        l_ptImmediateNotfnHeader->m_epersistcategory,
530                        l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory,
531                        l_ptImmediateNotfnHeader->m_cnotificationname);
532
533                 l_ptImmediateNotfnHeader->m_epersistcategory =
534                         l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory;
535               }
536             }
537
538             EFrameworkunifiedPersistCategory l_eOldPersistCategory = l_pChangePersistentCategory->m_eoldpersistcategory;
539
540             FRAMEWORKUNIFIEDLOG(ZONE_NPP_INFO, __FUNCTION__, "Changing persist category of %s from %d to %d",
541                    l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname,
542                    l_eOldPersistCategory,
543                    l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory);
544
545             // write data to emmc
546             l_estatus = SynchronousWritePersistentData(
547                         l_pChangePersistentCategory->m_tnornotifInfoheader.m_cpublishername,
548                         l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname,
549                         static_cast<PVOID>(l_pui8Data),
550                         l_pChangePersistentCategory->m_tnornotifInfoheader.m_uimsgsize,
551                         l_pChangePersistentCategory->m_tnornotifInfoheader.m_uidelay,
552                         l_pChangePersistentCategory->m_tnornotifInfoheader.m_uimaxmsglength,
553                         l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory);
554
555             // Create the old file path string to be removed
556             std::string l_cPath = IMMEDIATE_PERSISTENCE_STORAGE_V2;
557             std::string l_cTempPath = l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname;
558             size_t l_uiTempPathSize = 0;
559
560             // replace all '/' by '_'
561             l_uiTempPathSize = l_cTempPath.find_first_of("/");
562             while (std::string::npos != l_uiTempPathSize) {
563               l_cTempPath[l_uiTempPathSize] = '_';
564               l_uiTempPathSize = l_cTempPath.find_first_of("/", l_uiTempPathSize + 1);
565             }
566
567             switch (l_eOldPersistCategory) {
568               case eFrameworkunifiedFactoryData:
569                 l_cPath.append(FACTORYDATADIR);
570                 break;
571               case eFrameworkunifiedFactoryCustomerData:
572                 l_cPath.append(FACTORYCUSTOMERDATADIR);
573                 break;
574               case eFrameworkunifiedDealerData:
575                 l_cPath.append(DEALERDATADIR);
576                 break;
577               case eFrameworkunifiedUserData:
578               default: {
579                   l_cPath.append(USERDATADIR);
580                   l_cPath.append(ALLUSERAPPDATADIR);
581                 }
582                 break;
583             }
584
585             l_cPath.append(IMMEDIATEDATADIR);
586             l_cPath.append(l_cTempPath);
587
588             l_cPath.append(l_pChangePersistentCategory->m_tnornotifInfoheader.m_cpublishername);
589
590             if (0 != unlink(l_cPath.c_str())) {
591               FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Error deleting file %s, errno=%d", l_cPath.c_str(), errno);
592             }
593           } else {
594             // LCOV_EXCL_START 6: notification must be in list
595             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
596             l_estatus = eFrameworkunifiedStatusFail;
597             FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Can't update persistent category, notfn %s not found in g_mtimers map",
598                    l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname != 0 ?
599                    l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname : NULL);
600             // LCOV_EXCL_STOP
601           }
602           g_objmutextimerdata.Unlock();
603         } else {
604           // LCOV_EXCL_START 4: NSFW error case
605           AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
606           FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedGetMsgDataOfSize failed while retrieving"
607                                          "immediate persistence notfn data. Status:0x%x ", l_estatus);
608           // LCOV_EXCL_STOP
609         }
610
611         delete[] l_pui32ReceivedData;
612         l_pui32ReceivedData = NULL;
613       } else {
614         // LCOV_EXCL_START 5: new's error case
615         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
616         l_estatus = eFrameworkunifiedStatusNullPointer;
617         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Unable to allocate data. Can't persist, errno=%d", errno);
618         // LCOV_EXCL_STOP
619       }
620     } else {
621       // LCOV_EXCL_START 200: l_ui32ReceivedDataLength is bigger than sizeof(TImmediatePersistenceChangeCategory)
622       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
623       l_estatus = eFrameworkunifiedStatusInvldBuf;
624       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Invalid data length received %d. Can't persist.", l_ui32ReceivedDataLength);
625       // LCOV_EXCL_STOP
626     }
627   } else {
628     // LCOV_EXCL_START 4: NSFW error case
629     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
630     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Invalid param, hthread is NULL");
631     l_estatus = eFrameworkunifiedStatusInvldParam;
632     // LCOV_EXCL_STOP
633   }
634
635   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
636   return l_estatus;
637 }
638
639 /////////////////////////////
640 /// Class: CTimerHelper
641 /////////////////////////////
642
643 ////////////////////////////////////////////////////////////////////////////////////////////////////
644 /// CTimerHelper
645 /// Constructor of CTimerHelper class
646 ////////////////////////////////////////////////////////////////////////////////////////////////////
647 CTimerHelper::CTimerHelper() {
648   static UI_32 l_uiTimerCounter  = PROTOCOL_FRAMEWORKUNIFIED_BASE_CMD;
649   l_uiTimerCounter++;
650   m_uiCmdId = l_uiTimerCounter;
651   m_pui8HeaderAndData = NULL;
652 }
653
654 ////////////////////////////////////////////////////////////////////////////////////////////////////
655 /// ~CTimerHelper
656 /// Destructor of CTimerHelper class
657 ////////////////////////////////////////////////////////////////////////////////////////////////////
658 CTimerHelper::~CTimerHelper() {
659   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
660
661   if (NULL != m_pui8HeaderAndData) {
662     delete[] m_pui8HeaderAndData;
663     m_pui8HeaderAndData = NULL;
664   }
665
666   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
667 }
668
669 ////////////////////////////////////////////////////////////////////////////////////////////////////
670 /// GetCmdId
671 /// Returns id for timer
672 ////////////////////////////////////////////////////////////////////////////////////////////////////
673 UI_32 CTimerHelper::GetCmdId() {
674   return m_uiCmdId;
675 }
676
677 ////////////////////////////////////////////////////////////////////////////////////////////////////
678 /// OnTimeOut
679 /// This function writes the corresponding data in NOR when timer expires.
680 ////////////////////////////////////////////////////////////////////////////////////////////////////
681 EFrameworkunifiedStatus CTimerHelper::OnTimeOut(HANDLE hthread) {
682   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
683   EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
684
685   g_objmutextimerdata.ReadLock();
686   if (NULL != m_pui8HeaderAndData) {  // LCOV_EXCL_BR_LINE 200: m_pui8HeaderAndData can't be null
687     TNorPersistenceNotifInfoHeader *l_ptImmediateNotfnHeader =
688       static_cast<TNorPersistenceNotifInfoHeader *>(static_cast<PVOID>(m_pui8HeaderAndData));
689     PUI_8 l_pui8Data = m_pui8HeaderAndData + sizeof(TNorPersistenceNotifInfoHeader);
690     HANDLE l_hReceiverMq = McOpenSender(l_ptImmediateNotfnHeader->m_cpublishername);
691
692     // write data to emmc
693     l_estatus = SynchronousWritePersistentData(l_ptImmediateNotfnHeader->m_cpublishername,
694                                                l_ptImmediateNotfnHeader->m_cnotificationname,
695                                                static_cast<PVOID>(l_pui8Data),
696                                                l_ptImmediateNotfnHeader->m_uimsgsize,
697                                                l_ptImmediateNotfnHeader->m_uidelay,
698                                                l_ptImmediateNotfnHeader->m_uimaxmsglength,
699                                                l_ptImmediateNotfnHeader->m_epersistcategory);
700
701     // update corresponding application about data written status.
702     if (NULL != l_hReceiverMq) {  // LCOV_EXCL_BR_LINE 5: NSFW error case
703       NC_ImmediateWriteAck l_tWriteAck = {};
704       std::strncpy(l_tWriteAck.notificationName, l_ptImmediateNotfnHeader->m_cnotificationname,
705                    sizeof(l_tWriteAck.notificationName) - 1);
706       l_tWriteAck.eStatus = l_estatus;
707
708       if (eFrameworkunifiedStatusOK != (l_estatus = McSend(l_hReceiverMq, AppName, NPS_IMMEDIATE_WRITE_ACK, sizeof(l_tWriteAck),  // LCOV_EXCL_BR_LINE 4: NSFW error case.  // NOLINT[whitespace/line_length]
709                                               &l_tWriteAck))) {
710         // LCOV_EXCL_START 4: NSFW error case.
711         AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
712         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
713                "Error Sending NPS_IMMEDIATE_WRITE_ACK to %s for %s, Status: %d",
714                l_ptImmediateNotfnHeader->m_cpublishername != 0 ? l_ptImmediateNotfnHeader->m_cpublishername : NULL,
715                l_ptImmediateNotfnHeader->m_cnotificationname != 0 ?
716                l_ptImmediateNotfnHeader->m_cnotificationname : NULL,
717                l_estatus);
718         // LCOV_EXCL_STOP
719       }
720       McClose(l_hReceiverMq);
721       l_hReceiverMq = NULL;
722     } else {
723       // LCOV_EXCL_START 5: NSFW error case
724       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
725       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
726              "Error creating sender handle for service %s, Notification name %s Write Status: %d",
727              l_ptImmediateNotfnHeader->m_cpublishername != 0 ? l_ptImmediateNotfnHeader->m_cpublishername : NULL,
728              l_ptImmediateNotfnHeader->m_cnotificationname != 0 ?
729              l_ptImmediateNotfnHeader->m_cnotificationname : NULL,
730              l_estatus);
731       l_estatus = eFrameworkunifiedStatusNullPointer;
732       // LCOV_EXCL_STOP
733     }
734   } else {
735     // LCOV_EXCL_START 200: m_pui8HeaderAndData can't be null
736     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Not writing immediate persistence data. Data is NULL");
737     l_estatus = eFrameworkunifiedStatusNullPointer;
738     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
739     // LCOV_EXCL_STOP
740   }
741   g_objmutextimerdata.Unlock();
742
743   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
744   return l_estatus;
745 }
746
747 /// EOF