Remove unused directories and files in video_in_hal
[staging/basesystem.git] / service / native / framework_unified / client / NS_RingBuffer / src / ns_ringbuffer.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 /// \ingroup  tag_NSRingBuffer
19 /// \brief    This file contains implementation of class CNSRingBuffer.
20 ///           This class provides API to open, read, write and close ring buffer
21 ///
22 ////////////////////////////////////////////////////////////////////////////////////////////////////
23
24 ////////////////////////////////////////////////////////////////////////////////////////////////////
25 // Include Files
26 ////////////////////////////////////////////////////////////////////////////////////////////////////
27 #include <unistd.h>
28 #include <sys/mman.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <limits.h>
36
37 #include <native_service/ns_ringbuffer.h>
38 #include <native_service/cl_lock.h>
39
40 #include <string>
41
42 #define RBUF_HEADER_EXT "Hdr"
43 #define RBUF_RETRY_SLEEP (1000)
44 #define RBUF_RETRY_COUNT (8)
45 #define RBUF_PAGE_SIZE (4096)
46 #define RBUF_PAGE_ALIGN(p) ((p / RBUF_PAGE_SIZE) * RBUF_PAGE_SIZE)
47
48 ////////////////////////////////////////////////////////////////////////////////////////////////
49 /// CNSRingBuffer
50 /// Parameterized Constructor of CNSRingBuffer class
51 ////////////////////////////////////////////////////////////////////////////////////////////////
52 CNSRingBuffer::CNSRingBuffer(const std::string &f_cMappedFilePath, const UI_32 f_uiSize, int f_lid):
53   m_cMappedFilePath(f_cMappedFilePath), m_uiRingBuffSize(f_uiSize), m_pRbufMtx(NULL), m_pRbufHdr(NULL), m_pRbuf(NULL),
54   m_lid(f_lid), m_pLockAddr(NULL), m_siProcessLastWrtPage(-1) {  // LCOV_EXCL_BR_LINE 11: except branch
55   m_cMappedFileHdrPath = f_cMappedFilePath;
56   m_cMappedFileHdrPath.append(RBUF_HEADER_EXT);  // LCOV_EXCL_BR_LINE 11: except branch
57
58   m_cRbufMtxName = f_cMappedFilePath;
59   std::size_t found = m_cRbufMtxName.find_first_of('/');
60   while (found != std::string::npos) {
61     m_cRbufMtxName[found] = '_';
62     found = m_cRbufMtxName.find_first_of('/', found + 1);
63   }
64   m_cRbufMtxName[0] = '/';
65   pthread_mutex_init(&m_tOpenMutex, NULL);
66 }
67
68 ////////////////////////////////////////////////////////////////////////////////////////////////
69 /// CNSRingBuffer
70 /// Constructor of CNSRingBuffer class
71 ////////////////////////////////////////////////////////////////////////////////////////////////
72 CNSRingBuffer::CNSRingBuffer():
73   m_cMappedFilePath(""), m_uiRingBuffSize(0), m_pRbufMtx(NULL), m_pRbufHdr(NULL), m_pRbuf(NULL), m_lid(-1),
74   m_pLockAddr(NULL), m_siProcessLastWrtPage(-1) {
75   pthread_mutex_init(&m_tOpenMutex, NULL);
76 }
77
78 ////////////////////////////////////////////////////////////////////////////////////////////////
79 /// ~CNSRingBuffer
80 /// Destructor of CNSRingBuffer class
81 ////////////////////////////////////////////////////////////////////////////////////////////////
82 CNSRingBuffer::~CNSRingBuffer() {
83   if (NULL != m_pRbufHdr) {
84     // un-map the ring buffer object
85     Close();
86
87     m_pRbufHdr = NULL;
88     m_pRbufMtx = NULL;
89   }
90   pthread_mutex_destroy(&m_tOpenMutex);
91 }
92
93 ////////////////////////////////////////////////////////////////////////////////////////////////
94 /// Open
95 /// This function opens and maps the ring buffer object.
96 /// It creates the ring buffer if it does not exists.
97 ////////////////////////////////////////////////////////////////////////////////////////////////
98 EFrameworkunifiedStatus CNSRingBuffer::Open() {
99   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusErrOther;
100
101   pthread_mutex_lock(&m_tOpenMutex);
102
103   if (NULL == m_pRbufMtx) {
104     // Open ring buffer mutex
105     if (eFrameworkunifiedStatusOK != (l_eStatus = MapSM(reinterpret_cast<PVOID *>(&m_pRbufMtx),
106       m_cRbufMtxName, sizeof(NSRingBufferMtx)))) {
107       if (ENOENT == errno) {
108         errno = EOK;
109
110
111 //        if (eFrameworkunifiedStatusOK == CreateRBMutex()) {
112         EFrameworkunifiedStatus l_eStatus1 = CreateRBMutex();
113         if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) {
114
115           l_eStatus = MapSM(reinterpret_cast<PVOID *>(&m_pRbufMtx), m_cRbufMtxName, sizeof(NSRingBufferMtx));
116         }
117       }
118     } else {
119       if (m_pRbufMtx->m_lid != m_lid) {
120         // Different Lock ID in constructor parameter and mutex object
121         l_eStatus = eFrameworkunifiedStatusInvldParam;
122       }
123     }
124   }
125
126   if (eFrameworkunifiedStatusOK == l_eStatus) {
127     if (m_lid >= 0 && NULL == m_pLockAddr) {
128       CL_LockProcessInit();
129       if ((m_pLockAddr = CL_LockMap(m_lid)) == MAP_FAILED) {
130         l_eStatus = eFrameworkunifiedStatusFail;
131       }
132     }
133   }
134
135   if (eFrameworkunifiedStatusOK == l_eStatus) {
136     if (NULL == m_pRbufHdr) {
137       // Open header ring buffer
138       if (eFrameworkunifiedStatusOK != (l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbufHdr),
139         m_cMappedFileHdrPath, sizeof(NSRingBufferHdr)))) {
140         if (ENOENT == errno) {    // ring buffer is not created yet
141           errno = EOK;
142
143           // Create ring buffer
144
145 //          if (eFrameworkunifiedStatusOK == CreateRBHeader()) {
146           EFrameworkunifiedStatus l_eStatus1 = CreateRBHeader();
147           if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) {
148
149             // Retry to open
150             l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbufHdr),
151               m_cMappedFileHdrPath, sizeof(NSRingBufferHdr));
152
153 //          }
154           } else {
155             l_eStatus = l_eStatus1;
156           }
157
158         }
159       } else {
160
161 #if 0
162         LockMtx();
163
164         struct stat st;
165         int ret = stat(m_cMappedFilePath.c_str(), &st);
166
167         if (m_uiRingBuffSize == 0) {
168           if (ret == 0) {   // LCOV_EXCL_BR_LINE 5:stat's error case.
169             // LCOV_EXCL_START 5: stat's error case.
170             AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
171             if ((UI_32)st.st_size != m_pRbufHdr->m_uiRingBufferSize || (UI_32)st.st_size < m_pRbufHdr->m_uiReadPtr
172                 || (UI_32)st.st_size < m_pRbufHdr->m_uiWritePtr) {
173               memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
174               m_pRbufHdr->m_uiRingBufferSize = static_cast<UI_32>(st.st_size);
175               unlink(m_cMappedFilePath.c_str());
176             }
177             m_uiRingBuffSize = static_cast<UI_32>(st.st_size);
178             // LCOV_EXCL_STOP
179           }
180         } else {
181           if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize || m_uiRingBuffSize < m_pRbufHdr->m_uiReadPtr
182               || m_uiRingBuffSize < m_pRbufHdr->m_uiWritePtr || (ret == 0 && m_uiRingBuffSize != (UI_32)st.st_size)) {
183             memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
184             m_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
185             unlink(m_cMappedFilePath.c_str());
186           }
187         }
188
189         UnlockMtx();
190 #endif
191         int ret;
192         if ( (ret = LockMtx()) == 0) {
193           struct stat st;
194           int ret = stat(m_cMappedFilePath.c_str(), &st);
195
196           if (m_uiRingBuffSize == 0) {
197             if (ret == 0) {
198               if ((UI_32)st.st_size != m_pRbufHdr->m_uiRingBufferSize || (UI_32)st.st_size < m_pRbufHdr->m_uiReadPtr ||
199                   (UI_32)st.st_size < m_pRbufHdr->m_uiWritePtr) {
200                 memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
201                 m_pRbufHdr->m_uiRingBufferSize = static_cast<UI_32>(st.st_size);
202                 unlink(m_cMappedFilePath.c_str());
203               }
204               m_uiRingBuffSize = static_cast<UI_32>(st.st_size);
205             }
206           } else {
207             if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize || m_uiRingBuffSize < m_pRbufHdr->m_uiReadPtr ||
208                 m_uiRingBuffSize < m_pRbufHdr->m_uiWritePtr || (ret == 0 && m_uiRingBuffSize != (UI_32)st.st_size)) {
209               memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
210               m_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
211               unlink(m_cMappedFilePath.c_str());
212             }
213           }
214
215           UnlockMtx();
216         } else {
217           fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
218           munmap(m_pRbufHdr, sizeof(NSRingBufferHdr));
219           m_pRbufHdr = NULL;
220           l_eStatus = eFrameworkunifiedStatusFail;
221         }
222
223       }
224     }
225   }
226
227   if (eFrameworkunifiedStatusOK == l_eStatus && 0 != m_uiRingBuffSize) {
228     if (NULL == m_pRbuf) {
229       // Open ring buffer data buffer, create if not exists
230       if (eFrameworkunifiedStatusOK != (l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbuf),
231         m_cMappedFilePath, m_uiRingBuffSize))) {
232         if (ENOENT == errno) {   // ring buffer is not created yet
233           // Create ring buffer
234
235 //          if (eFrameworkunifiedStatusOK == CreateRBDataBuffer()) {
236           EFrameworkunifiedStatus l_eStatus1 = CreateRBDataBuffer();
237           if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) {
238
239             // Retry to open
240             l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbuf),
241               m_cMappedFilePath, m_uiRingBuffSize);
242           }
243         }
244       }
245     }
246   }
247
248   pthread_mutex_unlock(&m_tOpenMutex);
249
250   return l_eStatus;
251 }
252
253 ////////////////////////////////////////////////////////////////////////////////////////////////
254 /// IsOpen
255 /// This function is used to check whether the ring buffer is opened or not.
256 ////////////////////////////////////////////////////////////////////////////////////////////////
257 BOOL CNSRingBuffer::IsOpen() {
258   return NULL == m_pRbufHdr ? FALSE : TRUE;
259 }
260
261 ////////////////////////////////////////////////////////////////////////////////////////////////
262 /// Close
263 /// This function closes the ring buffer object.
264 ////////////////////////////////////////////////////////////////////////////////////////////////
265 EFrameworkunifiedStatus CNSRingBuffer::Close() {
266   if (NULL != m_pLockAddr) {
267     CL_LockUnmap(m_pLockAddr);
268   }
269
270   EFrameworkunifiedStatus l_eStatus1 = UnMap(m_pRbufHdr, sizeof(NSRingBufferHdr));
271   m_pRbufHdr = NULL;
272
273   EFrameworkunifiedStatus l_eStatus2 = eFrameworkunifiedStatusOK;
274   if (0 != m_uiRingBuffSize) {
275     l_eStatus2 = UnMap(m_pRbuf, m_uiRingBuffSize);
276     m_pRbuf = NULL;
277   }
278
279   EFrameworkunifiedStatus l_eStatus3 = UnMap(m_pRbufMtx, sizeof(NSRingBufferMtx));
280   m_pRbufMtx = NULL;
281
282   return (eFrameworkunifiedStatusOK != l_eStatus1 || eFrameworkunifiedStatusOK != l_eStatus2 ||
283           eFrameworkunifiedStatusOK != l_eStatus3) ? eFrameworkunifiedStatusFail : eFrameworkunifiedStatusOK;
284 }
285
286 ////////////////////////////////////////////////////////////////////////////////////////////////
287 /// Read
288 /// This function reads data from the ring buffer.
289 ////////////////////////////////////////////////////////////////////////////////////////////////
290 SI_32 CNSRingBuffer::Read(PSTR f_pBuffer, const UI_32 f_uilength) {
291   SI_32 l_iReadSize = -1;
292
293   if ((NULL != f_pBuffer) && (NULL != m_pRbufHdr) && (0 != f_uilength)) {
294     UI_32 l_uiDataSizeToRead = 0;
295
296     // Remaining buffer size from read pointer to end of the buffer
297     UI_32 l_uiRemainSize = 0;
298
299
300 #if 0
301     LockMtx();
302
303     // if ring buffer size is changed by some other process, remap the updated buffer size in this process
304     // ring buffer size can only be changed if the initial size is 0.
305     if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize) {
306       if (eFrameworkunifiedStatusOK == Map(reinterpret_cast<PVOID *>(&m_pRbuf),
307         m_cMappedFilePath, m_pRbufHdr->m_uiRingBufferSize)) {
308         m_uiRingBuffSize = m_pRbufHdr->m_uiRingBufferSize;
309       }
310     }
311
312     if (NULL != m_pRbuf) {
313       l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiReadPtr;
314
315       // Round read data size depending on un-read data size in the buffer
316       l_uiDataSizeToRead = m_pRbufHdr->m_uiUnReadSize < f_uilength ? m_pRbufHdr->m_uiUnReadSize : f_uilength;
317
318       if (l_uiRemainSize < l_uiDataSizeToRead) {
319         // Wrapping read
320         memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiRemainSize);
321         memcpy(f_pBuffer + l_uiRemainSize, m_pRbuf, l_uiDataSizeToRead - l_uiRemainSize);
322         m_pRbufHdr->m_uiReadPtr = l_uiDataSizeToRead - l_uiRemainSize;
323       } else {
324         memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiDataSizeToRead);
325
326         m_pRbufHdr->m_uiReadPtr += l_uiDataSizeToRead;
327
328         // Read pointer is the end of the buffer
329         if (m_pRbufHdr->m_uiReadPtr == m_uiRingBuffSize) {
330           m_pRbufHdr->m_uiReadPtr = 0;
331         }
332       }
333
334       m_pRbufHdr->m_uiUnReadSize -= l_uiDataSizeToRead;  // Update un-read data size
335
336       l_iReadSize = l_uiDataSizeToRead;
337     }
338
339     UnlockMtx();
340 #endif
341     int ret;
342     if ( (ret = LockMtx()) == 0) {
343       // if ring buffer size is changed by some other process, remap the updated buffer size in this process
344       // ring buffer size can only be changed if the initial size is 0.
345       if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize) {
346         if (eFrameworkunifiedStatusOK == Map(reinterpret_cast<PVOID *>(&m_pRbuf),
347           m_cMappedFilePath, m_pRbufHdr->m_uiRingBufferSize)) {
348           m_uiRingBuffSize = m_pRbufHdr->m_uiRingBufferSize;
349         }
350       }
351
352       if (NULL != m_pRbuf) {
353         l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiReadPtr;
354
355         // Round read data size depending on un-read data size in the buffer
356         l_uiDataSizeToRead = m_pRbufHdr->m_uiUnReadSize < f_uilength ? m_pRbufHdr->m_uiUnReadSize : f_uilength;
357
358           if (l_uiRemainSize < l_uiDataSizeToRead) {
359             // Wrapping read
360             memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiRemainSize);
361             memcpy(f_pBuffer + l_uiRemainSize, m_pRbuf, l_uiDataSizeToRead - l_uiRemainSize);
362             m_pRbufHdr->m_uiReadPtr = l_uiDataSizeToRead - l_uiRemainSize;
363           } else {
364             memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiDataSizeToRead);
365
366             m_pRbufHdr->m_uiReadPtr += l_uiDataSizeToRead;
367
368             // Read pointer is the end of the buffer
369             if (m_pRbufHdr->m_uiReadPtr == m_uiRingBuffSize) {
370               m_pRbufHdr->m_uiReadPtr = 0;
371             }
372           }
373
374           m_pRbufHdr->m_uiUnReadSize -= l_uiDataSizeToRead; // Update un-read data size
375
376           l_iReadSize = l_uiDataSizeToRead;
377         }
378
379         UnlockMtx();
380       } else {
381         fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
382         l_iReadSize = 0;
383     }
384
385   }
386
387   return l_iReadSize;
388 }
389
390 ////////////////////////////////////////////////////////////////////////////////////////////////
391 /// Write
392 /// This function writes the data into the ring buffer.
393 ////////////////////////////////////////////////////////////////////////////////////////////////
394 SI_32 CNSRingBuffer::Write(PCSTR f_pBuffer, const UI_32 f_uilength) {
395   SI_32 l_iWriteSize = -1;
396
397   // size available in buffer
398   UI_32 l_uiRemainSize = 0;
399
400   if (NULL != m_pRbufHdr && NULL != m_pRbuf && NULL != f_pBuffer && f_uilength <= m_uiRingBuffSize) {  // LCOV_EXCL_BR_LINE 11:except branch
401 #if 0
402     LockMtx();
403
404     UI_32 l_uiLastPage = RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr);
405     l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr;
406
407     if (m_siProcessLastWrtPage >= 0) {
408       if ((UI_32)m_siProcessLastWrtPage != l_uiLastPage) {
409         if (madvise(m_pRbuf + m_siProcessLastWrtPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
410           fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n",
411             m_pRbuf + m_siProcessLastWrtPage, strerror(errno));
412         }
413       }
414     }
415
416     // Write data to the buffer
417     if (l_uiRemainSize < f_uilength) {
418       // Wrapping write
419       memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, l_uiRemainSize);
420       memcpy(m_pRbuf, f_pBuffer + l_uiRemainSize, f_uilength - l_uiRemainSize);
421
422       // Update the write pointer
423       m_pRbufHdr->m_uiWritePtr = f_uilength - l_uiRemainSize;
424
425       // The buffer is full of valid data
426       m_pRbufHdr->m_bIsFull = TRUE;
427     } else {
428       memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, f_uilength);
429
430       // Update the write pointer
431       m_pRbufHdr->m_uiWritePtr += f_uilength;
432
433       // Write pointer is the end of the buffer
434       if (m_pRbufHdr->m_uiWritePtr == m_uiRingBuffSize) {
435         m_pRbufHdr->m_uiWritePtr = 0;
436
437         // The buffer is full of valid data
438         m_pRbufHdr->m_bIsFull = TRUE;
439       }
440     }
441
442     // Update un-read data size
443     m_pRbufHdr->m_uiUnReadSize += f_uilength;
444
445     // Set read pointer to be same as write pointer if write pointer exceeds the read pointer
446     if (m_uiRingBuffSize < m_pRbufHdr->m_uiUnReadSize) {
447       m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
448       m_pRbufHdr->m_uiUnReadSize = m_uiRingBuffSize;
449     }
450
451     while (l_uiLastPage != RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr)) {
452       if (madvise(m_pRbuf + l_uiLastPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
453         fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n", m_pRbuf + l_uiLastPage, strerror(errno));
454       }
455       l_uiLastPage += RBUF_PAGE_SIZE;
456       if (l_uiLastPage >= m_uiRingBuffSize) {
457         l_uiLastPage = 0;
458       }
459     }
460     m_siProcessLastWrtPage = (SI_32)l_uiLastPage;
461
462     UnlockMtx();
463
464     l_iWriteSize = f_uilength;
465 #endif
466     int ret;
467     if ( (ret = LockMtx()) == 0) {
468       UI_32 l_uiLastPage = RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr);
469       l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr;
470
471       if (m_siProcessLastWrtPage >= 0) {
472         if ((UI_32)m_siProcessLastWrtPage != l_uiLastPage) {
473           if (madvise(m_pRbuf + m_siProcessLastWrtPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
474             fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n",
475                     m_pRbuf + m_siProcessLastWrtPage, strerror(errno));
476           }
477         }
478       }
479
480       // Write data to the buffer
481       if (l_uiRemainSize < f_uilength) {
482       // Wrapping write
483         memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, l_uiRemainSize);
484         memcpy(m_pRbuf, f_pBuffer + l_uiRemainSize, f_uilength - l_uiRemainSize);
485
486         // Update the write pointer
487         m_pRbufHdr->m_uiWritePtr = f_uilength - l_uiRemainSize;
488
489         // The buffer is full of valid data
490         m_pRbufHdr->m_bIsFull = TRUE;
491       } else {
492         memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, f_uilength);
493
494         // Update the write pointer
495         m_pRbufHdr->m_uiWritePtr += f_uilength;
496
497         // Write pointer is the end of the buffer
498         if (m_pRbufHdr->m_uiWritePtr == m_uiRingBuffSize) {
499           m_pRbufHdr->m_uiWritePtr = 0;
500
501           // The buffer is full of valid data
502           m_pRbufHdr->m_bIsFull = TRUE;
503         }
504       }
505
506       // Update un-read data size
507       m_pRbufHdr->m_uiUnReadSize += f_uilength;
508
509       // Set read pointer to be same as write pointer if write pointer exceeds the read pointer
510       if (m_uiRingBuffSize < m_pRbufHdr->m_uiUnReadSize) {
511         m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
512         m_pRbufHdr->m_uiUnReadSize = m_uiRingBuffSize;
513       }
514
515       while (l_uiLastPage != RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr)) {
516         if (madvise(m_pRbuf + l_uiLastPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
517           fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n",
518                   m_pRbuf + l_uiLastPage, strerror(errno));
519         }
520         l_uiLastPage += RBUF_PAGE_SIZE;
521         if (l_uiLastPage >= m_uiRingBuffSize) {
522           l_uiLastPage = 0;
523         }
524       }
525       m_siProcessLastWrtPage = (SI_32)l_uiLastPage;
526
527       UnlockMtx();
528
529       l_iWriteSize = f_uilength;
530     } else {
531       fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
532       l_iWriteSize = 0;
533     }
534
535   }
536
537   return l_iWriteSize;
538 }
539
540 ////////////////////////////////////////////////////////////////////////////////////////////////
541 /// DumpToFile
542 /// This function writes all the data in the buffer into provided file f_pPath.
543 ////////////////////////////////////////////////////////////////////////////////////////////////
544 EFrameworkunifiedStatus CNSRingBuffer::DumpToFile(PCSTR f_pPath, PUI_32 f_uiDumpSize) {
545   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
546
547   ssize_t l_iSize = 0;
548
549   SI_32 fd = -1;
550
551   if (NULL == f_uiDumpSize) {
552     return eFrameworkunifiedStatusNullPointer;
553   }
554   *f_uiDumpSize = 0;
555
556   if (NULL != f_pPath) {
557     if (NULL != m_pRbufHdr) {
558       // Open file
559       if (-1 != (fd = open(f_pPath, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640))) {
560         if (NULL != m_pRbuf && 0 != m_uiRingBuffSize) {
561
562 #if 0
563           LockMtx();
564           // Write buffer data to file
565           if (m_pRbufHdr->m_bIsFull) {
566             // Buffer has full of data (read data from write pointer)
567             if (-1 != (l_iSize = write(fd, m_pRbuf + m_pRbufHdr->m_uiWritePtr,
568               m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr))) {
569               *f_uiDumpSize += static_cast<UI_32>(l_iSize);
570             } else {
571               l_eStatus = eFrameworkunifiedStatusErrOther;
572             }
573           }
574
575           if (-1 != (l_iSize = write(fd, m_pRbuf, m_pRbufHdr->m_uiWritePtr))) {
576             *f_uiDumpSize += static_cast<UI_32>(l_iSize);
577           }
578
579           UnlockMtx();
580 #endif
581           int ret;
582           if ( (ret = LockMtx()) == 0) {
583             // Write buffer data to file
584             if (m_pRbufHdr->m_bIsFull) {
585               // Buffer has full of data (read data from write pointer)
586               if (-1 != (l_iSize = write(fd, m_pRbuf + m_pRbufHdr->m_uiWritePtr,
587                 m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr))) {
588
589 //                *f_uiDumpSize += l_iSize;
590                 *f_uiDumpSize += static_cast<UI_32>(l_iSize);
591               } else {
592                 l_eStatus = eFrameworkunifiedStatusErrOther;
593               }
594             }
595
596             if (-1 != (l_iSize = write(fd, m_pRbuf, m_pRbufHdr->m_uiWritePtr))) {
597
598 //              *f_uiDumpSize += l_iSize;
599               *f_uiDumpSize += static_cast<UI_32>(l_iSize);
600             }
601
602             UnlockMtx();
603           } else {
604             fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
605           }
606
607         } else if (NULL == m_pRbuf && 0 != m_uiRingBuffSize) {
608           l_eStatus = eFrameworkunifiedStatusFail;
609         } else {
610           // do nothing
611         }
612
613         // Sync the file to force I/O operation completed
614         fsync(fd);
615
616         close(fd);
617       } else {
618         l_eStatus = eFrameworkunifiedStatusFileLoadError;
619       }
620     } else {
621       l_eStatus = eFrameworkunifiedStatusFail;
622     }
623   } else {
624     l_eStatus = eFrameworkunifiedStatusInvldParam;
625   }
626
627   return l_eStatus;
628 }
629
630 ////////////////////////////////////////////////////////////////////////////////////////////////
631 /// GetSize
632 /// This function returns the number of unread bytes which can be read by Read().
633 ////////////////////////////////////////////////////////////////////////////////////////////////
634 SI_32 CNSRingBuffer::GetSize() {
635   SI_32 l_uiReadSize = -1;
636
637   if (NULL != m_pRbufHdr) {
638     l_uiReadSize = m_pRbufHdr->m_uiUnReadSize;
639   }
640
641   return l_uiReadSize;
642 }
643
644 ////////////////////////////////////////////////////////////////////////////////////////////////
645 /// ClearBuf
646 /// This function clears the buffer.
647 ////////////////////////////////////////////////////////////////////////////////////////////////
648 EFrameworkunifiedStatus CNSRingBuffer::ClearBuf() {
649   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
650
651   if (NULL != m_pRbufHdr) {
652
653 #if 0
654     LockMtx();
655
656     // Initialize the r/w pointers
657     m_pRbufHdr->m_uiReadPtr = 0;
658     m_pRbufHdr->m_uiWritePtr = 0;
659     m_pRbufHdr->m_uiUnReadSize = 0;
660     m_pRbufHdr->m_bIsFull = FALSE;
661
662     UnlockMtx();
663 #endif
664     int ret;
665     if ((ret = LockMtx()) == 0) {
666       // Initialize the r/w pointers
667       m_pRbufHdr->m_uiReadPtr = 0;
668       m_pRbufHdr->m_uiWritePtr = 0;
669       m_pRbufHdr->m_uiUnReadSize = 0;
670       m_pRbufHdr->m_bIsFull = FALSE;
671
672       UnlockMtx();
673     } else {
674       fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
675     }
676
677   } else {
678     l_eStatus = eFrameworkunifiedStatusFail;
679   }
680
681   return l_eStatus;
682 }
683
684 ////////////////////////////////////////////////////////////////////////////////////////////////
685 /// SetReadPtrToWritePtr
686 /// This function sets the position of read ptr to write ptr in buffer.
687 ////////////////////////////////////////////////////////////////////////////////////////////////
688 EFrameworkunifiedStatus CNSRingBuffer::SetReadPtrToWritePtr() {
689   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
690
691   if (NULL != m_pRbufHdr) {
692
693 #if 0
694     LockMtx();
695
696     // Initialize the r/w pointers
697     m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
698     m_pRbufHdr->m_uiUnReadSize = 0;
699
700     UnlockMtx();
701 #endif
702     int ret;
703     if ( (ret = LockMtx()) == 0) {
704       // Initialize the r/w pointers
705       m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
706       m_pRbufHdr->m_uiUnReadSize = 0;
707
708       UnlockMtx();
709     } else {
710       fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
711     }
712
713   } else {
714     l_eStatus = eFrameworkunifiedStatusFail;
715   }
716
717   return l_eStatus;
718 }
719 //
720 ////////////////////////////////////////////////////////////////////////////////////////////////
721 /// CreateRBMutex
722 /// This function creates the shared memory object for mutex.
723 ////////////////////////////////////////////////////////////////////////////////////////////////
724 EFrameworkunifiedStatus CNSRingBuffer::CreateRBMutex() {
725   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
726
727   // file descriptor of shared memory
728   SI_32 l_siId = -1;
729
730   // ring buffer mutex
731   NSRingBufferMtx *l_pRbufMtx = NULL;
732
733   if ((!m_cRbufMtxName.empty()) || (m_cRbufMtxName.size() <= NAME_MAX)) {
734     // Try to create shared memory
735     l_siId = shm_open(m_cRbufMtxName.c_str(), O_CREAT | O_EXCL | O_RDWR, 0640);
736
737     if (-1 != l_siId) {
738       // Set the size of shared memory
739       if (-1 != ftruncate(l_siId, sizeof(NSRingBufferMtx))) {
740         // Map the shared memory
741         l_pRbufMtx = reinterpret_cast<NSRingBufferMtx *>(mmap(NULL,
742           sizeof(NSRingBufferMtx), (PROT_READ | PROT_WRITE), MAP_SHARED, l_siId, 0));
743
744         if (MAP_FAILED != l_pRbufMtx) {
745           if (m_lid == -1) {
746             // mutex attribute
747             pthread_mutexattr_t l_tMtxAttr = {};
748
749             // Initialize mutex
750             pthread_mutexattr_init(&l_tMtxAttr);
751             pthread_mutexattr_setpshared(&l_tMtxAttr, PTHREAD_PROCESS_SHARED);
752             pthread_mutex_init(&l_pRbufMtx->m_tBufMutex, &l_tMtxAttr);
753             pthread_mutexattr_destroy(&l_tMtxAttr);
754
755             l_eStatus = eFrameworkunifiedStatusOK;
756           } else {
757             // CL_Lock
758             l_eStatus = eFrameworkunifiedStatusOK;
759           }
760           l_pRbufMtx->m_lid = m_lid;
761
762           // Once initialized un-map the shared memory
763           munmap(l_pRbufMtx, sizeof(NSRingBufferMtx));
764         }
765       }
766
767       close(l_siId);
768     } else if (EEXIST == errno) {
769       // Shared memory is already created
770       l_eStatus = eFrameworkunifiedStatusDuplicate;
771     } else {
772       // do nothing
773     }
774   } else {
775     l_eStatus = eFrameworkunifiedStatusInvldParam;
776   }
777
778   return l_eStatus;
779 }
780
781 ////////////////////////////////////////////////////////////////////////////////////////////////
782 /// CreateRBHeader
783 /// This function creates the ring buffer object for header.
784 ////////////////////////////////////////////////////////////////////////////////////////////////
785 EFrameworkunifiedStatus CNSRingBuffer::CreateRBHeader() {
786   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
787
788   // file descriptor of ring buffer
789   SI_32 l_siFd = -1;
790
791   // ring buffer headers
792   NSRingBufferHdr *l_pRbufHdr = NULL;
793
794   if (!m_cMappedFileHdrPath.empty()) {  // LCOV_EXCL_BR_LINE 11: except branch
795     // Try to create ring buffer
796     l_siFd = open(m_cMappedFileHdrPath.c_str(), O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0640);
797
798     if (-1 != l_siFd) {
799       // Set the size of ring buffer
800       if (-1 != ftruncate(l_siFd, sizeof(NSRingBufferHdr))) {
801         // Map the ring buffer
802         l_pRbufHdr = reinterpret_cast<NSRingBufferHdr *>(mmap(NULL,
803           sizeof(NSRingBufferHdr), (PROT_READ | PROT_WRITE), MAP_SHARED, l_siFd, 0));
804
805         if (MAP_FAILED != l_pRbufHdr) {
806
807 #if 0
808           LockMtx();
809
810           // Initialize the r/w pointers
811           l_pRbufHdr->m_uiReadPtr = 0;
812           l_pRbufHdr->m_uiWritePtr = 0;
813           l_pRbufHdr->m_uiUnReadSize = 0;
814           l_pRbufHdr->m_bIsFull = FALSE;
815           l_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
816
817           UnlockMtx();
818 #endif
819           int ret;
820           if ( (ret = LockMtx()) == 0) {
821             // Initialize the r/w pointers
822             l_pRbufHdr->m_uiReadPtr = 0;
823             l_pRbufHdr->m_uiWritePtr = 0;
824             l_pRbufHdr->m_uiUnReadSize = 0;
825             l_pRbufHdr->m_bIsFull = FALSE;
826             l_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
827
828             UnlockMtx();
829             l_eStatus = eFrameworkunifiedStatusOK;
830           } else {
831             fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
832             l_eStatus = eFrameworkunifiedStatusFail;
833           }
834
835
836           // Once initialized un-map the ring buffer
837           munmap(l_pRbufHdr, sizeof(NSRingBufferHdr));
838         }
839       }
840
841       close(l_siFd);
842     } else if (EEXIST == errno) {
843       // ring buffer is already created
844       l_eStatus = eFrameworkunifiedStatusDuplicate;
845     } else {
846       // do nothing
847     }
848   } else {
849     l_eStatus = eFrameworkunifiedStatusInvldParam;
850   }
851
852   return l_eStatus;
853 }
854
855 ////////////////////////////////////////////////////////////////////////////////////////////////
856 /// CreateRBDataBuffer
857 /// This function creates the ring buffer object for data buffer.
858 ////////////////////////////////////////////////////////////////////////////////////////////////
859 EFrameworkunifiedStatus CNSRingBuffer::CreateRBDataBuffer() {
860   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
861
862   // file descriptor of ring buffer
863   SI_32 l_siFd = -1;
864
865   if (!m_cMappedFilePath.empty()) {
866     // Try to create ring buffer
867     l_siFd = open(m_cMappedFilePath.c_str(), O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0640);
868
869     if (-1 != l_siFd) {
870       // Set the size of ring buffer
871       if (-1 != ftruncate(l_siFd, m_uiRingBuffSize)) {
872         l_eStatus = eFrameworkunifiedStatusOK;
873       }
874
875       close(l_siFd);
876     } else if (EEXIST == errno) {
877       // ring buffer is already created
878       l_eStatus = eFrameworkunifiedStatusDuplicate;
879     } else {
880       // do nothing
881     }
882   } else {
883     l_eStatus = eFrameworkunifiedStatusInvldParam;
884   }
885
886   return l_eStatus;
887 }
888
889 ////////////////////////////////////////////////////////////////////////////////////////////////
890 /// MapRBHeader
891 /// This function open and maps in process space.
892 ////////////////////////////////////////////////////////////////////////////////////////////////
893 EFrameworkunifiedStatus CNSRingBuffer::Map(PVOID *f_pRbuf, const std::string &f_cMappedFile, const UI_32 f_uiRbufSize) {
894   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
895
896   // file descriptor of ring buffer
897   SI_32 l_siFd = -1;
898
899   // ring buffer headers
900   PVOID l_pRbuf = NULL;
901
902   // Open ring buffer
903   l_siFd = open(f_cMappedFile.c_str(), O_RDWR | O_CLOEXEC, NULL);
904
905   if (-1 != l_siFd) {
906     if (CheckSize(l_siFd, f_uiRbufSize) == eFrameworkunifiedStatusOK) {
907       // Map the ring buffer into its memory space
908       l_pRbuf = mmap(NULL, f_uiRbufSize, (PROT_READ | PROT_WRITE), MAP_SHARED, l_siFd, 0);
909
910       if (MAP_FAILED != l_pRbuf) {
911         *f_pRbuf = l_pRbuf;
912         l_eStatus = eFrameworkunifiedStatusOK;
913       }
914     }
915
916     close(l_siFd);
917   }
918
919   return l_eStatus;
920 }
921
922 ////////////////////////////////////////////////////////////////////////////////////////////////
923 /// CheckSize
924 /// This function check mmap size
925 ////////////////////////////////////////////////////////////////////////////////////////////////
926 EFrameworkunifiedStatus CNSRingBuffer::CheckSize(int fd, off_t size) {
927   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
928   struct stat st;
929   int i;
930
931   for (i = 0; i < RBUF_RETRY_COUNT; i++) {
932     if (fstat(fd, &st) < 0) {
933       fprintf(stderr, "[CNSRingBuffer::CheckSize] fstat error: %s\n", strerror(errno));
934       goto out;
935     }
936     if (st.st_size == size) {
937       l_eStatus = eFrameworkunifiedStatusOK;
938       break;
939     }
940     usleep(RBUF_RETRY_SLEEP);
941   }
942   if (i >= RBUF_RETRY_COUNT) {
943     errno = ENOMEM;
944   }
945
946 out:
947   return l_eStatus;
948 }
949
950 ////////////////////////////////////////////////////////////////////////////////////////////////
951 /// MapSM
952 /// This function shm_open and maps the shared memory in process space.
953 ////////////////////////////////////////////////////////////////////////////////////////////////
954 EFrameworkunifiedStatus CNSRingBuffer::MapSM(PVOID *f_pShMem, const std::string &f_cShmName, const UI_32 f_uiShmSize) {
955   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
956
957   // file descriptor of shared memory
958   SI_32 l_siId = -1;
959
960   // shared memory buffer headers
961   PVOID l_pShmBuf = NULL;
962
963   // Open shared memory
964   l_siId = shm_open(f_cShmName.c_str(), O_RDWR, 0640);
965
966   if (-1 != l_siId) {
967     if (CheckSize(l_siId, f_uiShmSize) == eFrameworkunifiedStatusOK) {
968       // Map the shared memory into its memory space
969       l_pShmBuf = mmap(NULL, f_uiShmSize, (PROT_READ | PROT_WRITE), MAP_SHARED, l_siId, 0);
970
971       if (MAP_FAILED != l_pShmBuf) {
972         *f_pShMem = l_pShmBuf;
973         l_eStatus = eFrameworkunifiedStatusOK;
974       }
975     }
976
977     close(l_siId);
978   }
979
980   return l_eStatus;
981 }
982
983 ////////////////////////////////////////////////////////////////////////////////////////////////
984 /// UnMap
985 /// This function unmaps object.
986 ////////////////////////////////////////////////////////////////////////////////////////////////
987 EFrameworkunifiedStatus CNSRingBuffer::UnMap(PVOID f_pRbuf, const UI_32 f_uiRbufSize) {
988   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
989
990   // Un-map the ring buffer
991   if (NULL != f_pRbuf) {
992     if (0 != munmap(f_pRbuf, f_uiRbufSize)) {
993       l_eStatus = eFrameworkunifiedStatusFail;
994     }
995   } else {
996     l_eStatus = eFrameworkunifiedStatusNullPointer;
997   }
998
999   return l_eStatus;
1000 }
1001
1002
1003 //void CNSRingBuffer::LockMtx() {
1004 //  if (m_lid == -1) {
1005 //    pthread_mutex_lock(&m_pRbufMtx->m_tBufMutex);
1006 //  } else {
1007 //    CL_LockGet(m_pLockAddr);
1008 //  }
1009 //}
1010 int CNSRingBuffer::LockMtx() {
1011   int ret = 0;
1012
1013   if (m_lid == -1) {
1014     ret = pthread_mutex_lock(&m_pRbufMtx->m_tBufMutex);
1015   } else {
1016     ret = CL_LockGet(m_pLockAddr);
1017   }
1018
1019   return ret;
1020 }
1021
1022
1023 void CNSRingBuffer::UnlockMtx() {
1024   if (m_lid == -1) {
1025     pthread_mutex_unlock(&m_pRbufMtx->m_tBufMutex);
1026   } else {
1027     CL_LockRelease(m_pLockAddr);
1028   }
1029 }