Skip to content

Commit 1e23f4e

Browse files
authored
Merge pull request #142 from rdkcentral/develop
rebase
2 parents a9df9c8 + cea5fcf commit 1e23f4e

15 files changed

Lines changed: 1310 additions & 303 deletions

build_inside_container.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ autoreconf --install
2727
# FLags to print compiler warnings
2828
DEBUG_CFLAGS="-Wall -Werror -Wextra"
2929

30-
export CFLAGS=" ${DEBUG_CFLAGS} -I${INSTALL_DIR}/include/rtmessage -I${INSTALL_DIR}/include/msgpack -I${INSTALL_DIR}/include/rbus -I${INSTALL_DIR}/include -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/local/include -DFEATURE_SUPPORT_WEBCONFIG -DRDK_LOGGER"
30+
export CFLAGS=" ${DEBUG_CFLAGS} -I${INSTALL_DIR}/include/rtmessage -I${INSTALL_DIR}/include/msgpack -I${INSTALL_DIR}/include/rbus -I${INSTALL_DIR}/include -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/local/include -DFEATURE_SUPPORT_WEBCONFIG -DRDK_LOGGER -DPERSIST_LOG_MON_REF"
3131

3232
export LDFLAGS="-L/usr/lib/x86_64-linux-gnu -lglib-2.0"
3333

source/dcautil/dca.c

Lines changed: 82 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#include <sys/stat.h>
3131
#include <sys/mman.h>
3232
#include <limits.h>
33-
33+
#include <sys/sendfile.h>
3434
#include <cjson/cJSON.h>
3535

3636
#include "dcautil.h"
@@ -98,14 +98,15 @@ static const char *strnstr(const char *haystack, const char *needle, size_t len)
9898

9999
for (size_t i = 0; i + needle_len <= len; i++)
100100
{
101-
if (memcmp(haystack + i, needle, needle_len) == 0)
102-
{
103-
return haystack + i;
104-
}
105101
if (haystack[i] == '\0')
106102
{
107103
break;
108104
}
105+
if (memcmp(haystack + i, needle, needle_len) == 0)
106+
{
107+
return haystack + i;
108+
}
109+
109110
}
110111
return NULL;
111112
}
@@ -144,10 +145,7 @@ int processTopPattern(char* profileName, Vector* topMarkerList, Vector* out_gre
144145
size_t var = 0;
145146
size_t vCount = Vector_Size(topMarkerList);
146147
T2Debug("topMarkerList for profile %s is of count = %lu \n", profileName, (unsigned long )vCount);
147-
// Get logfile -> seek value map associated with the profile
148148

149-
// We are getting the exec count directly from the profileExecCounter parameter
150-
//int profileExecCounter = gsProfile->execCounter;
151149
char* filename = NULL;
152150

153151
for (var = 0; var < vCount; ++var)
@@ -159,6 +157,10 @@ int processTopPattern(char* profileName, Vector* topMarkerList, Vector* out_gre
159157
}
160158
int tmp_skip_interval, is_skip_param;
161159
tmp_skip_interval = grepMarkerObj->skipFreq;
160+
if(tmp_skip_interval <= 0)
161+
{
162+
tmp_skip_interval = 0;
163+
}
162164
is_skip_param = (profileExecCounter % (tmp_skip_interval + 1) == 0) ? 0 : 1;
163165
if (is_skip_param != 0)
164166
{
@@ -193,6 +195,10 @@ int processTopPattern(char* profileName, Vector* topMarkerList, Vector* out_gre
193195
// If the skip frequency is set, skip the marker processing for this interval
194196
int tmp_skip_interval, is_skip_param;
195197
tmp_skip_interval = grepMarkerObj->skipFreq;
198+
if(tmp_skip_interval <= 0)
199+
{
200+
tmp_skip_interval = 0;
201+
}
196202
is_skip_param = (profileExecCounter % (tmp_skip_interval + 1) == 0) ? 0 : 1;
197203
if (is_skip_param != 0)
198204
{
@@ -509,7 +515,6 @@ static char* getAbsolutePatternMatch(FileDescriptor* fileDescriptor, const char*
509515
static int processPatternWithOptimizedFunction(const GrepMarker* marker, Vector* out_grepResultList, FileDescriptor* filedescriptor)
510516
{
511517
// Sanitize the input
512-
513518
const char* memmmapped_data_cf = filedescriptor->cfaddr;
514519
if (!marker || !out_grepResultList || !memmmapped_data_cf)
515520
{
@@ -547,7 +552,6 @@ static int processPatternWithOptimizedFunction(const GrepMarker* marker, Vector*
547552
{
548553
// Get the last occurrence of the pattern in the memory-mapped data
549554
last_found = getAbsolutePatternMatch(filedescriptor, pattern);
550-
// TODO : If trimParameter is true, trim the pattern before adding to the result list
551555
if (last_found)
552556
{
553557
// If a match is found, process it accordingly
@@ -598,7 +602,6 @@ static int getLogFileDescriptor(GrepSeekProfile* gsProfile, const char* logPath,
598602
return -1;
599603
}
600604

601-
// Calculate the file size
602605
struct stat sb;
603606
if (fstat(fd, &sb) == -1)
604607
{
@@ -607,7 +610,6 @@ static int getLogFileDescriptor(GrepSeekProfile* gsProfile, const char* logPath,
607610
return -1;
608611
}
609612

610-
// Check if the file size is 0
611613
if (sb.st_size == 0)
612614
{
613615
T2Error("The size of the logfile is 0 for %s\n", logFile);
@@ -665,7 +667,6 @@ static int getRotatedLogFileDescriptor(const char* logPath, const char* logFile)
665667
return -1;
666668
}
667669

668-
// Calculate the file size
669670
struct stat rb;
670671
if (fstat(rd, &rb) == -1)
671672
{
@@ -692,10 +693,12 @@ static void freeFileDescriptor(FileDescriptor* fileDescriptor)
692693
if(fileDescriptor->baseAddr)
693694
{
694695
munmap(fileDescriptor->baseAddr, fileDescriptor->cf_file_size);
696+
fileDescriptor->baseAddr = NULL;
695697
}
696698
if(fileDescriptor->rotatedAddr)
697699
{
698700
munmap(fileDescriptor->rotatedAddr, fileDescriptor->rf_file_size);
701+
fileDescriptor->rotatedAddr = NULL;
699702
}
700703
fileDescriptor->cfaddr = NULL;
701704
fileDescriptor->rfaddr = NULL;
@@ -736,7 +739,7 @@ static FileDescriptor* getFileDeltaInMemMapAndSearch(const int fd, const off_t s
736739
off_t offset_in_page_size_multiple ;
737740
unsigned int bytes_ignored = 0, bytes_ignored_main = 0, bytes_ignored_rotated = 0;
738741
// Find the nearest multiple of page size
739-
if (seek_value > 0)
742+
if (seek_value > 0 && PAGESIZE > 0)
740743
{
741744
offset_in_page_size_multiple = (seek_value / PAGESIZE) * PAGESIZE;
742745
bytes_ignored = seek_value - offset_in_page_size_multiple;
@@ -746,64 +749,88 @@ static FileDescriptor* getFileDeltaInMemMapAndSearch(const int fd, const off_t s
746749
offset_in_page_size_multiple = 0;
747750
bytes_ignored = 0;
748751
}
752+
//create a tmp file for main file fd
753+
char tmp_fdmain[] = "/tmp/dca_tmpfile_fdmainXXXXXX";
754+
int tmp_fd = mkstemp(tmp_fdmain);
755+
if (tmp_fd == -1)
756+
{
757+
T2Error("Failed to create temp file: %s\n", strerror(errno));
758+
return NULL;
759+
}
760+
unlink(tmp_fdmain);
761+
off_t offset = 0;
762+
ssize_t sent = sendfile(tmp_fd, fd, &offset, sb.st_size);
763+
if (sent != sb.st_size)
764+
{
765+
T2Error("sendfile failed: %s\n", strerror(errno));
766+
close(tmp_fd);
767+
return NULL;
768+
}
749769

750770
if(seek_value > sb.st_size || check_rotated == true)
751771
{
752772
int rd = getRotatedLogFileDescriptor(logPath, logFile);
753-
if (rd == -1)
773+
if (rd != -1 && fstat(rd, &rb) == 0 && rb.st_size > 0)
754774
{
755-
T2Error("Error opening rotated file. Start search in current file\n");
756-
T2Debug("File size rounded to nearest page size used for offset read: %jd bytes\n", (intmax_t)offset_in_page_size_multiple);
757-
addrcf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, offset_in_page_size_multiple);
758-
bytes_ignored_main = bytes_ignored;
759-
}
760-
else
761-
{
762-
int fs = 0;
763-
fs = fstat(rd, &rb);
764-
if(fs == -1)
775+
char tmp_fdrotated[] = "/tmp/dca_tmpfile_fdrotatedXXXXXX";
776+
int tmp_rd = mkstemp(tmp_fdrotated);
777+
if (tmp_rd == -1)
765778
{
766-
T2Error("Error getting file size\n");
767-
close(rd);
779+
T2Error("Failed to create temp file: %s\n", strerror(errno));
780+
return NULL;
768781
}
769-
else
782+
unlink(tmp_fdrotated);
783+
offset = 0;
784+
sent = sendfile(tmp_rd, rd, &offset, rb.st_size);
785+
if (sent != rb.st_size)
770786
{
771-
if(rb.st_size == 0)
772-
{
773-
T2Error("The Size of the logfile is 0\n");
774-
close(rd);
775-
}
787+
T2Error("sendfile failed: %s\n", strerror(errno));
788+
close(tmp_rd);
789+
return NULL;
776790
}
777-
778-
if(rb.st_size > 0)
791+
addrcf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, tmp_fd, 0);
792+
addrrf = mmap(NULL, rb.st_size, PROT_READ, MAP_PRIVATE, tmp_rd, offset_in_page_size_multiple);
793+
bytes_ignored_rotated = bytes_ignored;
794+
close(rd);
795+
close(tmp_rd);
796+
rd = -1;
797+
}
798+
else
799+
{
800+
T2Error("Error opening rotated file. Start search in current file\n");
801+
T2Debug("File size rounded to nearest page size used for offset read: %jd bytes\n", (intmax_t)offset_in_page_size_multiple);
802+
if(seek_value < sb.st_size)
779803
{
780-
addrcf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
781-
addrrf = mmap(NULL, rb.st_size, PROT_READ, MAP_PRIVATE, rd, offset_in_page_size_multiple);
782-
bytes_ignored_rotated = bytes_ignored;
783-
if(rd != -1)
784-
{
785-
close(rd);
786-
rd = -1;
787-
}
804+
addrcf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, tmp_fd, offset_in_page_size_multiple);
805+
bytes_ignored_main = bytes_ignored;
788806
}
789-
790-
791-
if(rb.st_size == 0 && fs == -1)
807+
else
792808
{
793-
T2Debug("No contents in rotated log file. File size rounded to nearest page size used for offset read: %jd bytes\n", (intmax_t)offset_in_page_size_multiple);
794-
addrcf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, offset_in_page_size_multiple);
795-
bytes_ignored_main = bytes_ignored;
809+
T2Debug("Log file got rotated. Ignoring invalid mapping\n");
810+
close(tmp_fd);
811+
close(fd);
812+
return NULL;
796813
}
797814
}
798815
}
799816
else
800817
{
801-
T2Info("File size rounded to nearest page size used for offset read: %jd bytes\n", (intmax_t)offset_in_page_size_multiple);
802-
addrcf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, offset_in_page_size_multiple);
803-
bytes_ignored_main = bytes_ignored;
804-
addrrf = NULL; // No rotated file in this case
818+
T2Debug("File size rounded to nearest page size used for offset read: %jd bytes\n", (intmax_t)offset_in_page_size_multiple);
819+
if(seek_value < sb.st_size)
820+
{
821+
addrcf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, tmp_fd, offset_in_page_size_multiple);
822+
bytes_ignored_main = bytes_ignored;
823+
}
824+
else
825+
{
826+
T2Debug("Log file got rotated. Ignoring invalid mapping\n");
827+
close(tmp_fd);
828+
close(fd);
829+
return NULL;
830+
}
831+
addrrf = NULL;
805832
}
806-
833+
close(tmp_fd);
807834
close(fd);
808835

809836
if (addrcf == MAP_FAILED)
@@ -871,12 +898,10 @@ static int parseMarkerListOptimized(GrepSeekProfile *gsProfile, Vector * ip_vMar
871898
}
872899

873900
char *prevfile = NULL;
874-
//GrepSeekProfile* gsProfile = NULL;
901+
875902
size_t var = 0;
876903
size_t vCount = Vector_Size(ip_vMarkerList);
877904

878-
// Get logfile -> seek value map associated with the profile
879-
//gsProfile = (GrepSeekProfile *) getLogSeekMapForProfile(profileName);
880905
if(NULL == gsProfile)
881906
{
882907
T2Error("%s Unable to retrieve/create logSeekMap for profile \n", __FUNCTION__);

test/functional-tests/features/telemetry_process_multiprofile.feature

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,65 @@ Scenario: Multiprofile with TriggerConditions
226226
Given When the telemetry daemon is already running
227227
When a multiprofile is configured with TriggerConditions
228228
Then Multiprofile should be accepted and report should be generated whenever trigger condition is triggered
229+
230+
Scenario: Check for HASH value matches of profile to avoid duplicate processing
231+
Given a multiprofile is running
232+
When another multiprofile with same name and hash is configured
233+
Then the configuration will be ignored
234+
235+
Scenario: Support for subscribing to TR181 Parameter value change
236+
Given a datamodel marker is configured as method subscribe
237+
When the tr181 parameter value changes
238+
Then the value change will be sent as an event to the telemetry daemon
239+
240+
Scenario: Data harvesting from previous logs folder for report profiles with log file search markers
241+
Given the device has logs from the previous session in the PreviousLogs folder
242+
When a profile goes through log files for report generation
243+
Then the log files in PreviousLogs folder will also be grepped for log lines
244+
245+
Scenario: Capability to support multiple split markers for the same log line
246+
When two split markers are configured for the same log line in a file
247+
Then both the markers will be reported
248+
249+
Scenario: Include data from data source Tr181 parameters as Accumulate
250+
Given a datamodel marker is configured as method subscribe and use accumulate
251+
When the tr181 parameter value changes multiple time inside the reporting interval
252+
Then all the changes will be reported with values
253+
254+
Scenario: Report sending over HTTP protocol
255+
Given a profile is confugred with report sending protocol as HTTP along with the respective endpoint
256+
Then the report will be sent to the configured endpoint
257+
258+
Scenario: Caching of upload failed reports
259+
Given a json report is attemplted to be sent the configured method
260+
When the attempt to send the report fails
261+
Then the report will be cached to be sent later along with the next report
262+
263+
Scenario: Report sending with protocol set as RBUS_METHOD in report profiles.
264+
Given a profile is confugred with report sending protocol as HTTP along with the respective datamodel
265+
Then the report will be configured to the respective datamodel
266+
267+
Scenario: Report generation for profiles with log grep markers during log file rotation scenarios
268+
Given a grep marker is configured
269+
When the respective log file reaches a certain limit and has been rotated
270+
Then the content of the roatated log file is also grepped for the search string
271+
272+
Scenario: Event accumulate with and without timestamp in report profiles for event markers and datamodel.
273+
Given an event marker or tr181 marker with subscribe are configured with reportTimeStamp
274+
When the event is sent to the telementry
275+
Then the telemetry report will have the time the event was received as timestamp
276+
277+
Scenario: Forced on demand reporting outside the regular reporting intervals.
278+
Given a single profile or a multiprofile is running
279+
When kill signal 29 is sent to the telemetry daemon
280+
Then a reportwill be generated immediately for all the running profiles
281+
282+
Scenario: Stress testing of interaction with rbus interface to check for any deadlocks or rbus timeouts.
283+
Given telemetry is running and an event marker is configured
284+
When the configured event markers is sent in large numbers without any interval
285+
Then all the events should be captured and telemetry daemon should not be crashing
286+
287+
Scenario: profile persistence
288+
Given a multiprofile is expired
289+
When the telemetry is restarted
290+
Then the profile will be enabled after restart
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
####################################################################################
2+
# If not stated otherwise in this file or this component's Licenses
3+
# following copyright and licenses apply:
4+
#
5+
# Copyright 2024 RDK Management
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
####################################################################################
19+
20+
21+
Feature: Telemetry Single profile configuration and report generation
22+
23+
Scenario: Single profile configuration with event marker and use as accumulate
24+
Given When the telemetry daemon is already running
25+
When a single profile is configured with event marker and use as accumulate
26+
Then generated report should contain the values for all occurrences of the marker
27+
28+
Scenario: Capability to support multiple split markers for the same log line
29+
When two split markers are configured for the same log line in a file
30+
Then both the markers will be reported
31+
32+
Scenario: Caching of upload failed reports
33+
Given a json report is attemplted to be sent the configured method
34+
When the attempt to send the report fails
35+
Then the report will be cached to be sent later along with the next report
36+
37+
Scenario: Data harvesting from previous logs folder for report profiles with log file search markers
38+
Given the device has logs from the previous session in the PreviousLogs folder
39+
When a profile goes through log files for report generation
40+
Then the log files in PreviousLogs folder will also be grepped for log lines

0 commit comments

Comments
 (0)