• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "memory_data_plugin.h"
16 
17 #include <sstream>
18 
19 #include "buffer_splitter.h"
20 #include "securec.h"
21 #include "smaps_stats.h"
22 
23 namespace {
24 const char* CMD_FORMAT = "memory service meminfo --local ";
25 constexpr size_t READ_BUFFER_SIZE = 1024 * 16;
26 constexpr int BUF_MAX_LEN = 2048;
27 } // namespace
28 
MemoryDataPlugin()29 MemoryDataPlugin::MemoryDataPlugin()
30     : buffer_(new (std::nothrow) uint8_t[READ_BUFFER_SIZE]), meminfoFd_(-1), vmstatFd_(-1), err_(-1)
31 {
32     InitProto2StrVector();
33     SetPath(const_cast<char*>("/proc"));
34 }
35 
~MemoryDataPlugin()36 MemoryDataPlugin::~MemoryDataPlugin()
37 {
38     HILOG_INFO(LOG_CORE, "%s:~MemoryDataPlugin!", __func__);
39 
40     buffer_ = nullptr;
41 
42     if (meminfoFd_ > 0) {
43         close(meminfoFd_);
44         meminfoFd_ = -1;
45     }
46     if (vmstatFd_ > 0) {
47         close(vmstatFd_);
48         vmstatFd_ = -1;
49     }
50     for (auto it = pidFds_.begin(); it != pidFds_.end(); it++) {
51         for (int i = FILE_STATUS; i <= FILE_SMAPS; i++) {
52             if (it->second[i] != -1) {
53                 close(it->second[i]);
54             }
55         }
56     }
57     return;
58 }
59 
InitProto2StrVector()60 void MemoryDataPlugin::InitProto2StrVector()
61 {
62     int maxprotobufid = 0;
63     for (unsigned int i = 0; i < sizeof(meminfoMapping) / sizeof(meminfoMapping[0]); i++) {
64         maxprotobufid = std::max(meminfoMapping[i].protobufid, maxprotobufid);
65     }
66     meminfoStrList_.resize(maxprotobufid + 1);
67 
68     for (unsigned int i = 0; i < sizeof(meminfoMapping) / sizeof(meminfoMapping[0]); i++) {
69         meminfoStrList_[meminfoMapping[i].protobufid] = meminfoMapping[i].procstr;
70     }
71 
72     maxprotobufid = 0;
73     for (unsigned int i = 0; i < sizeof(vmeminfoMapping) / sizeof(vmeminfoMapping[0]); i++) {
74         maxprotobufid = std::max(vmeminfoMapping[i].protobufid, maxprotobufid);
75     }
76     vmstatStrList_.resize(maxprotobufid + 1);
77 
78     for (unsigned int i = 0; i < sizeof(vmeminfoMapping) / sizeof(vmeminfoMapping[0]); i++) {
79         vmstatStrList_[vmeminfoMapping[i].protobufid] = vmeminfoMapping[i].procstr;
80     }
81 
82     return;
83 }
84 
InitMemVmemFd()85 int MemoryDataPlugin::InitMemVmemFd()
86 {
87     if (protoConfig_.report_sysmem_mem_info()) {
88         char fileName[PATH_MAX + 1] = {0};
89         char realPath[PATH_MAX + 1] = {0};
90         if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1, "%s/meminfo", testpath_) < 0) {
91             HILOG_ERROR(LOG_CORE, "%s:snprintf_s error", __func__);
92             return RET_FAIL;
93         }
94         if (realpath(fileName, realPath) == nullptr) {
95             const int bufSize = 1024;
96             char buf[bufSize] = { 0 };
97             strerror_r(errno, buf, bufSize);
98             HILOG_ERROR(LOG_CORE, "%s:realpath failed, errno(%d:%s)", __func__, errno, buf);
99             return RET_FAIL;
100         }
101         meminfoFd_ = open(realPath, O_RDONLY | O_CLOEXEC);
102         if (meminfoFd_ == -1) {
103             const int bufSize = 1024;
104             char buf[bufSize] = { 0 };
105             strerror_r(errno, buf, bufSize);
106             HILOG_ERROR(LOG_CORE, "%s:open failed, fileName, errno(%d:%s)", __func__, errno, buf);
107             return RET_FAIL;
108         }
109     }
110 
111     if (protoConfig_.report_sysmem_vmem_info()) {
112         char fileName[PATH_MAX + 1] = {0};
113         char realPath[PATH_MAX + 1] = {0};
114         if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1, "%s/vmstat", testpath_) < 0) {
115             HILOG_ERROR(LOG_CORE, "%s:snprintf_s error", __func__);
116             return RET_FAIL;
117         }
118         if (realpath(fileName, realPath) == nullptr) {
119             const int bufSize = 1024;
120             char buf[bufSize] = { 0 };
121             strerror_r(errno, buf, bufSize);
122             HILOG_ERROR(LOG_CORE, "%s:realpath failed, errno(%d:%s)", __func__, errno, buf);
123             return RET_FAIL;
124         }
125         vmstatFd_ = open(realPath, O_RDONLY | O_CLOEXEC);
126         if (vmstatFd_ == -1) {
127             const int bufSize = 1024;
128             char buf[bufSize] = { 0 };
129             strerror_r(errno, buf, bufSize);
130             HILOG_ERROR(LOG_CORE, "%s:failed to open(/proc/vmstat), errno(%d:%s)", __func__, errno, buf);
131             return RET_FAIL;
132         }
133     }
134 
135     return RET_SUCC;
136 }
137 
Start(const uint8_t * configData,uint32_t configSize)138 int MemoryDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
139 {
140     if (buffer_ == nullptr) {
141         HILOG_ERROR(LOG_CORE, "%s:buffer_ == null", __func__);
142         return RET_FAIL;
143     }
144 
145     if (protoConfig_.ParseFromArray(configData, configSize) <= 0) {
146         HILOG_ERROR(LOG_CORE, "%s:parseFromArray failed!", __func__);
147         return RET_FAIL;
148     }
149 
150     if (InitMemVmemFd() != RET_SUCC) {
151         return RET_FAIL;
152     }
153 
154     if (protoConfig_.sys_meminfo_counters().size() > 0) {
155         for (int i = 0; i < protoConfig_.sys_meminfo_counters().size(); i++) {
156             if ((size_t)protoConfig_.sys_meminfo_counters(i) >= meminfoStrList_.size()) {
157                 HILOG_ERROR(LOG_CORE, "%s:sys meminfo counter index invalid!", __func__);
158                 return RET_FAIL;
159             }
160             if (meminfoStrList_[protoConfig_.sys_meminfo_counters(i)]) {
161                 meminfoCounters_.emplace(meminfoStrList_[protoConfig_.sys_meminfo_counters(i)],
162                                          protoConfig_.sys_meminfo_counters(i));
163             }
164         }
165     }
166 
167     if (protoConfig_.sys_vmeminfo_counters().size() > 0) {
168         for (int i = 0; i < protoConfig_.sys_vmeminfo_counters().size(); i++) {
169             if ((size_t)protoConfig_.sys_vmeminfo_counters(i) >= vmstatStrList_.size()) {
170                 HILOG_ERROR(LOG_CORE, "%s:vmstat counter index invalid!", __func__);
171                 return RET_FAIL;
172             }
173             if (vmstatStrList_[protoConfig_.sys_vmeminfo_counters(i)]) {
174                 vmstatCounters_.emplace(vmstatStrList_[protoConfig_.sys_vmeminfo_counters(i)],
175                                         protoConfig_.sys_vmeminfo_counters(i));
176             }
177         }
178     }
179 
180     if (protoConfig_.pid().size() > 0) {
181         for (int i = 0; i < protoConfig_.pid().size(); i++) {
182             int32_t pid = protoConfig_.pid(i);
183             pidFds_.emplace(pid, OpenProcPidFiles(pid));
184         }
185     }
186 
187     HILOG_INFO(LOG_CORE, "%s:start success!", __func__);
188     return RET_SUCC;
189 }
190 
WriteMeminfo(MemoryData & data)191 void MemoryDataPlugin::WriteMeminfo(MemoryData& data)
192 {
193     int readsize = ReadFile(meminfoFd_);
194     if (readsize == RET_FAIL) {
195         return;
196     }
197     BufferSplitter totalbuffer((const char*)buffer_.get(), readsize);
198 
199     do {
200         if (!totalbuffer.NextWord(':')) {
201             continue;
202         }
203         const_cast<char *>(totalbuffer.CurWord())[totalbuffer.CurWordSize()] = '\0';
204         auto it = meminfoCounters_.find(totalbuffer.CurWord());
205         if (it == meminfoCounters_.end()) {
206             continue;
207         }
208 
209         int counter_id = it->second;
210         if (!totalbuffer.NextWord(' ')) {
211             continue;
212         }
213         auto value = static_cast<uint64_t>(strtoll(totalbuffer.CurWord(), nullptr, DEC_BASE));
214         auto* meminfo = data.add_meminfo();
215 
216         meminfo->set_key(static_cast<SysMeminfoType>(counter_id));
217         meminfo->set_value(value);
218     } while (totalbuffer.NextLine());
219 
220     return;
221 }
222 
WriteVmstat(MemoryData & data)223 void MemoryDataPlugin::WriteVmstat(MemoryData& data)
224 {
225     int readsize = ReadFile(vmstatFd_);
226     if (readsize == RET_FAIL) {
227         return;
228     }
229     BufferSplitter totalbuffer((const char*)buffer_.get(), readsize);
230 
231     do {
232         if (!totalbuffer.NextWord(' ')) {
233             continue;
234         }
235         const_cast<char *>(totalbuffer.CurWord())[totalbuffer.CurWordSize()] = '\0';
236         auto it = vmstatCounters_.find(totalbuffer.CurWord());
237         if (it == vmstatCounters_.end()) {
238             continue;
239         }
240 
241         int counter_id = it->second;
242         char* valuestr = const_cast<char *>(totalbuffer.CurWord() + totalbuffer.CurWordSize() + 1);
243         valuestr[totalbuffer.CurLineSize() - (valuestr - totalbuffer.CurLine())] = '\0';
244 
245         auto value = static_cast<uint64_t>(strtoll(valuestr, nullptr, DEC_BASE));
246         auto* vmeminfo = data.add_vmeminfo();
247 
248         vmeminfo->set_key(static_cast<SysVMeminfoType>(counter_id));
249         vmeminfo->set_value(value);
250     } while (totalbuffer.NextLine());
251 
252     return;
253 }
254 
WriteAppsummary(ProcessMemoryInfo * processinfo,SmapsStats & smapInfo)255 void MemoryDataPlugin::WriteAppsummary(ProcessMemoryInfo* processinfo, SmapsStats& smapInfo)
256 {
257     processinfo->mutable_memsummary()->set_java_heap(smapInfo.GetProcessJavaHeap());
258     processinfo->mutable_memsummary()->set_native_heap(smapInfo.GetProcessNativeHeap());
259     processinfo->mutable_memsummary()->set_code(smapInfo.GetProcessCode());
260     processinfo->mutable_memsummary()->set_stack(smapInfo.GetProcessStack());
261     processinfo->mutable_memsummary()->set_graphics(smapInfo.GetProcessGraphics());
262     processinfo->mutable_memsummary()->set_private_other(smapInfo.GetProcessPrivateOther());
263     processinfo->mutable_memsummary()->set_system(smapInfo.GetProcessSystem());
264 }
265 
ParseNumber(std::string line)266 int MemoryDataPlugin::ParseNumber(std::string line)
267 {
268     return atoi(line.substr(line.find_first_of("01234567890")).c_str());
269 }
270 
ParseMemInfo(const char * data,ProcessMemoryInfo * memoryInfo)271 bool MemoryDataPlugin::ParseMemInfo(const char* data, ProcessMemoryInfo* memoryInfo)
272 {
273     bool ready = false;
274     bool done = false;
275     std::istringstream ss(data);
276     std::string line;
277 
278     while (std::getline(ss, line)) {
279         std::string s(line);
280         if (s.find("App Summary") != s.npos) {
281             ready = true;
282             continue;
283         }
284 
285         if (ready) {
286             if (s.find("Java Heap:") != s.npos) {
287                 memoryInfo->mutable_memsummary()->set_java_heap(ParseNumber(s));
288                 continue;
289             }
290             if (s.find("Native Heap:") != s.npos) {
291                 memoryInfo->mutable_memsummary()->set_native_heap(ParseNumber(s));
292                 continue;
293             }
294             if (s.find("Code:") != s.npos) {
295                 memoryInfo->mutable_memsummary()->set_code(ParseNumber(s));
296                 continue;
297             }
298             if (s.find("Stack:") != s.npos) {
299                 memoryInfo->mutable_memsummary()->set_stack(ParseNumber(s));
300                 continue;
301             }
302             if (s.find("Graphics:") != s.npos) {
303                 memoryInfo->mutable_memsummary()->set_graphics(ParseNumber(s));
304                 continue;
305             }
306             if (s.find("Private Other:") != s.npos) {
307                 memoryInfo->mutable_memsummary()->set_private_other(ParseNumber(s));
308                 continue;
309             }
310             if (s.find("System:") != s.npos) {
311                 memoryInfo->mutable_memsummary()->set_system(ParseNumber(s));
312                 done = true;
313                 break;
314             }
315         }
316     }
317     return done;
318 }
319 
GetMemInfoByMemoryService(uint32_t pid,ProcessMemoryInfo * memoryInfo)320 bool MemoryDataPlugin::GetMemInfoByMemoryService(uint32_t pid, ProcessMemoryInfo* memoryInfo)
321 {
322     std::string fullCmd = CMD_FORMAT + std::to_string(pid);
323 
324     std::unique_ptr<uint8_t[]> buffer {new (std::nothrow) uint8_t[BUF_MAX_LEN]};
325     std::unique_ptr<FILE, int (*)(FILE*)> fp(popen(fullCmd.c_str(), "r"), pclose);
326     if (!fp) {
327         HILOG_ERROR(LOG_CORE, "%s:popen error", __func__);
328         return false;
329     }
330 
331     fread(buffer.get(), 1, BUF_MAX_LEN, fp.get());
332     buffer.get()[BUF_MAX_LEN - 1] = '\0';
333 
334     return ParseMemInfo(reinterpret_cast<char*>(buffer.get()), memoryInfo);
335 }
336 
Report(uint8_t * data,uint32_t dataSize)337 int MemoryDataPlugin::Report(uint8_t* data, uint32_t dataSize)
338 {
339     MemoryData dataProto;
340     uint32_t length;
341 
342     if (protoConfig_.report_process_tree()) {
343         WriteProcesseList(dataProto);
344     }
345 
346     if (protoConfig_.report_sysmem_mem_info()) {
347         WriteMeminfo(dataProto);
348     }
349 
350     if (protoConfig_.report_sysmem_vmem_info()) {
351         WriteVmstat(dataProto);
352     }
353 
354     if (protoConfig_.pid().size() > 0) {
355         for (int i = 0; i < protoConfig_.pid().size(); i++) {
356             int32_t pid = protoConfig_.pid(i);
357             auto* processinfo = dataProto.add_processesinfo();
358             if (protoConfig_.report_process_mem_info()) {
359                 WriteProcinfoByPidfds(processinfo, pid);
360             }
361 
362             if (protoConfig_.report_app_mem_info() && !protoConfig_.report_app_mem_by_memory_service()) {
363                 SmapsStats smapInfo;
364                 smapInfo.ParseMaps(pid);
365                 WriteAppsummary(processinfo, smapInfo);
366             }
367         }
368     }
369 
370     length = dataProto.ByteSizeLong();
371     if (length > dataSize) {
372         return -length;
373     }
374     if (dataProto.SerializeToArray(data, length) > 0) {
375         return length;
376     }
377     return 0;
378 }
379 
Stop()380 int MemoryDataPlugin::Stop()
381 {
382     if (meminfoFd_ > 0) {
383         close(meminfoFd_);
384         meminfoFd_ = -1;
385     }
386     if (vmstatFd_ > 0) {
387         close(vmstatFd_);
388         vmstatFd_ = -1;
389     }
390     for (auto it = pidFds_.begin(); it != pidFds_.end(); it++) {
391         for (int i = FILE_STATUS; i <= FILE_SMAPS; i++) {
392             if (it->second[i] != -1) {
393                 close(it->second[i]);
394                 it->second[i] = -1;
395             }
396         }
397     }
398     HILOG_INFO(LOG_CORE, "%s:stop success!", __func__);
399     return 0;
400 }
401 
WriteProcinfoByPidfds(ProcessMemoryInfo * processinfo,int32_t pid)402 void MemoryDataPlugin::WriteProcinfoByPidfds(ProcessMemoryInfo* processinfo, int32_t pid)
403 {
404     char* end = nullptr;
405     int32_t readSize;
406 
407     readSize = ReadFile(pidFds_[pid][FILE_STATUS]);
408     if (readSize != RET_FAIL) {
409         WriteProcess(processinfo, (char*)buffer_.get(), readSize, pid);
410     } else {
411         SetEmptyProcessInfo(processinfo);
412     }
413     if (ReadFile(pidFds_[pid][FILE_OOM]) != RET_FAIL) {
414         processinfo->set_oom_score_adj(static_cast<int64_t>(strtol((char*)buffer_.get(), &end, DEC_BASE)));
415     } else {
416         processinfo->set_oom_score_adj(0);
417     }
418     return;
419 }
420 
ReadFile(int fd)421 int32_t MemoryDataPlugin::ReadFile(int fd)
422 {
423     if ((buffer_.get() == nullptr) || (fd == -1)) {
424         return RET_FAIL;
425     }
426     int readsize = pread(fd, buffer_.get(), READ_BUFFER_SIZE - 1, 0);
427     if (readsize <= 0) {
428         const int bufSize = 1024;
429         char buf[bufSize] = { 0 };
430         strerror_r(errno, buf, bufSize);
431         HILOG_ERROR(LOG_CORE, "%s:failed to read(%d), errno(%d:%s)", __func__, fd, errno, buf);
432         err_ = errno;
433         return RET_FAIL;
434     }
435     return readsize;
436 }
437 
OpenProcPidFiles(int32_t pid)438 std::vector<int> MemoryDataPlugin::OpenProcPidFiles(int32_t pid)
439 {
440     char fileName[PATH_MAX + 1] = {0};
441     char realPath[PATH_MAX + 1] = {0};
442     int count = sizeof(procfdMapping) / sizeof(procfdMapping[0]);
443     std::vector<int> profds;
444 
445     for (int i = 0; i < count; i++) {
446         if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1,
447             "%s/%d/%s", testpath_, pid, procfdMapping[i].file) < 0) {
448             HILOG_ERROR(LOG_CORE, "%s:snprintf_s error", __func__);
449         }
450         if (realpath(fileName, realPath) == nullptr) {
451             const int bufSize = 1024;
452             char buf[bufSize] = { 0 };
453             strerror_r(errno, buf, bufSize);
454             HILOG_ERROR(LOG_CORE, "%s:realpath failed, errno(%d:%s)", __func__, errno, buf);
455         }
456         int fd = open(realPath, O_RDONLY | O_CLOEXEC);
457         if (fd == -1) {
458             const int bufSize = 1024;
459             char buf[bufSize] = { 0 };
460             strerror_r(errno, buf, bufSize);
461             HILOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName, errno, buf);
462         }
463         profds.emplace(profds.begin() + i, fd);
464     }
465     return profds;
466 }
467 
OpenDestDir(const char * dirPath)468 DIR* MemoryDataPlugin::OpenDestDir(const char* dirPath)
469 {
470     DIR* destDir = nullptr;
471 
472     destDir = opendir(dirPath);
473     if (destDir == nullptr) {
474         const int bufSize = 1024;
475         char buf[bufSize] = { 0 };
476         strerror_r(errno, buf, bufSize);
477         HILOG_ERROR(LOG_CORE, "%s:failed to opendir(%s), errno(%d:%s)", __func__, dirPath, errno, buf);
478     }
479 
480     return destDir;
481 }
482 
GetValidPid(DIR * dirp)483 int32_t MemoryDataPlugin::GetValidPid(DIR* dirp)
484 {
485     if (!dirp) return 0;
486     while (struct dirent* dirEnt = readdir(dirp)) {
487         if (dirEnt->d_type != DT_DIR) {
488             continue;
489         }
490 
491         int32_t pid = atoi(dirEnt->d_name);
492         if (pid) {
493             return pid;
494         }
495     }
496     return 0;
497 }
498 
ReadProcPidFile(int32_t pid,const char * pFileName)499 int32_t MemoryDataPlugin::ReadProcPidFile(int32_t pid, const char* pFileName)
500 {
501     char fileName[PATH_MAX + 1] = {0};
502     char realPath[PATH_MAX + 1] = {0};
503     int fd = -1;
504     ssize_t bytesRead = 0;
505 
506     if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1, "%s/%d/%s", testpath_, pid, pFileName) < 0) {
507         HILOG_ERROR(LOG_CORE, "%s:snprintf_s error", __func__);
508         return RET_FAIL;
509     }
510     if (realpath(fileName, realPath) == nullptr) {
511         const int bufSize = 1024;
512         char buf[bufSize] = { 0 };
513         strerror_r(errno, buf, bufSize);
514         HILOG_ERROR(LOG_CORE, "%s:realpath failed, errno(%d:%s)", __func__, errno, buf);
515         return RET_FAIL;
516     }
517     fd = open(realPath, O_RDONLY | O_CLOEXEC);
518     if (fd == -1) {
519         const int bufSize = 1024;
520         char buf[bufSize] = { 0 };
521         strerror_r(errno, buf, bufSize);
522         HILOG_INFO(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName, errno, buf);
523         err_ = errno;
524         return RET_FAIL;
525     }
526     if (buffer_.get() == nullptr) {
527         HILOG_INFO(LOG_CORE, "%s:empty address, buffer_ is NULL", __func__);
528         err_ = RET_NULL_ADDR;
529         close(fd);
530         return RET_FAIL;
531     }
532     bytesRead = read(fd, buffer_.get(), READ_BUFFER_SIZE - 1);
533     if (bytesRead < 0) {
534         close(fd);
535         const int bufSize = 1024;
536         char buf[bufSize] = { 0 };
537         strerror_r(errno, buf, bufSize);
538         HILOG_INFO(LOG_CORE, "%s:failed to read(%s), errno(%d:%s)", __func__, fileName, errno, buf);
539         err_ = errno;
540         return RET_FAIL;
541     }
542     buffer_.get()[bytesRead] = '\0';
543     close(fd);
544 
545     return bytesRead;
546 }
547 
BufnCmp(const char * src,int srcLen,const char * key,int keyLen)548 bool MemoryDataPlugin::BufnCmp(const char* src, int srcLen, const char* key, int keyLen)
549 {
550     if (!src || !key || (srcLen < keyLen)) {
551         return false;
552     }
553     for (int i = 0; i < keyLen; i++) {
554         if (*src++ != *key++) {
555             return false;
556         }
557     }
558     return true;
559 }
560 
addPidBySort(int32_t pid)561 bool MemoryDataPlugin::addPidBySort(int32_t pid)
562 {
563     auto pidsEnd = seenPids_.end();
564     auto it = std::lower_bound(seenPids_.begin(), pidsEnd, pid);
565     if (it != pidsEnd && *it == pid) {
566         return false;
567     }
568     it = seenPids_.insert(it, std::move(pid));
569     return true;
570 }
571 
GetProcStatusId(const char * src,int srcLen)572 int MemoryDataPlugin::GetProcStatusId(const char* src, int srcLen)
573 {
574     int count = sizeof(procStatusMapping) / sizeof(procStatusMapping[0]);
575     for (int i = 0; i < count; i++) {
576         if (BufnCmp(src, srcLen, procStatusMapping[i].procstr, strlen(procStatusMapping[i].procstr))) {
577             return procStatusMapping[i].procid;
578         }
579     }
580     return RET_FAIL;
581 }
582 
StringToUll(const char * word,uint64_t & value)583 bool MemoryDataPlugin::StringToUll(const char* word, uint64_t& value)
584 {
585     char* end = nullptr;
586     errno = 0;
587     value = strtoull(word, &end, DEC_BASE);
588     if ((errno == ERANGE && (value == ULLONG_MAX)) || (errno != 0 && value == 0)) {
589         return false;
590     } else if (end == word && (*word >= '0' && *word <= '9')) {
591         return false;
592     }
593 
594     return true;
595 }
596 
SetProcessInfo(ProcessMemoryInfo * processinfo,int key,const char * word)597 void MemoryDataPlugin::SetProcessInfo(ProcessMemoryInfo* processinfo, int key, const char* word)
598 {
599     uint64_t value;
600 
601     if ((key >= PRO_TGID && key <= PRO_VMHWM && key != PRO_NAME) && !StringToUll(word, value)) {
602         HILOG_ERROR(LOG_CORE, "MemoryDataPlugin:%s, strtoull failed, key(%d), word(%s)", __func__, key, word);
603         return;
604     }
605 
606     switch (key) {
607         case PRO_TGID:
608             processinfo->set_pid(static_cast<int32_t>(value));
609             break;
610         case PRO_VMSIZE:
611             processinfo->set_vm_size_kb(value);
612             break;
613         case PRO_VMRSS:
614             processinfo->set_vm_rss_kb(value);
615             break;
616         case PRO_RSSANON:
617             processinfo->set_rss_anon_kb(value);
618             break;
619         case PRO_RSSFILE:
620             processinfo->set_rss_file_kb(value);
621             break;
622         case PRO_RSSSHMEM:
623             processinfo->set_rss_shmem_kb(value);
624             break;
625         case PRO_VMSWAP:
626             processinfo->set_vm_swap_kb(value);
627             break;
628         case PRO_VMLCK:
629             processinfo->set_vm_locked_kb(value);
630             break;
631         case PRO_VMHWM:
632             processinfo->set_vm_hwm_kb(value);
633             break;
634         default:
635             break;
636     }
637     return;
638 }
639 
WriteProcess(ProcessMemoryInfo * processinfo,const char * pFile,uint32_t fileLen,int32_t pid)640 void MemoryDataPlugin::WriteProcess(ProcessMemoryInfo* processinfo, const char* pFile, uint32_t fileLen, int32_t pid)
641 {
642     BufferSplitter totalbuffer(const_cast<const char*>(pFile), fileLen + 1);
643 
644     do {
645         totalbuffer.NextWord(':');
646         if (!totalbuffer.CurWord()) {
647             return;
648         }
649 
650         int key = GetProcStatusId(totalbuffer.CurWord(), totalbuffer.CurWordSize());
651         totalbuffer.NextWord('\n');
652         if (!totalbuffer.CurWord()) {
653             continue;
654         }
655         if (key == PRO_NAME) {
656             processinfo->set_name(totalbuffer.CurWord(), totalbuffer.CurWordSize());
657         }
658         SetProcessInfo(processinfo, key, totalbuffer.CurWord());
659     } while (totalbuffer.NextLine());
660     // update process name
661     int32_t ret = ReadProcPidFile(pid, "cmdline");
662     if (ret > 0) {
663         processinfo->set_name(reinterpret_cast<char*>(buffer_.get()), strlen(reinterpret_cast<char*>(buffer_.get())));
664     }
665 }
666 
SetEmptyProcessInfo(ProcessMemoryInfo * processinfo)667 void MemoryDataPlugin::SetEmptyProcessInfo(ProcessMemoryInfo* processinfo)
668 {
669     processinfo->set_pid(-1);
670     processinfo->set_name("null");
671     processinfo->set_vm_size_kb(0);
672     processinfo->set_vm_rss_kb(0);
673     processinfo->set_rss_anon_kb(0);
674     processinfo->set_rss_file_kb(0);
675     processinfo->set_rss_shmem_kb(0);
676     processinfo->set_vm_swap_kb(0);
677     processinfo->set_vm_locked_kb(0);
678     processinfo->set_vm_hwm_kb(0);
679     processinfo->set_oom_score_adj(0);
680 }
681 
WriteOomInfo(ProcessMemoryInfo * processinfo,int32_t pid)682 void MemoryDataPlugin::WriteOomInfo(ProcessMemoryInfo* processinfo, int32_t pid)
683 {
684     char* end = nullptr;
685 
686     if (ReadProcPidFile(pid, "oom_score_adj") == RET_FAIL) {
687         processinfo->set_oom_score_adj(0);
688         return;
689     }
690     if (buffer_.get() == nullptr) {
691         processinfo->set_oom_score_adj(0);
692         HILOG_ERROR(LOG_CORE, "%s:invalid params, read buffer_ is NULL", __func__);
693         return;
694     }
695     processinfo->set_oom_score_adj(static_cast<int64_t>(strtol((char*)buffer_.get(), &end, DEC_BASE)));
696 }
697 
WriteProcessInfo(MemoryData & data,int32_t pid)698 void MemoryDataPlugin::WriteProcessInfo(MemoryData& data, int32_t pid)
699 {
700     int32_t ret = ReadProcPidFile(pid, "status");
701     if (ret == RET_FAIL) {
702         SetEmptyProcessInfo(data.add_processesinfo());
703         return;
704     }
705     if ((buffer_.get() == nullptr) || (ret == 0)) {
706         return;
707     }
708     auto* processinfo = data.add_processesinfo();
709     WriteProcess(processinfo, (char*)buffer_.get(), ret, pid);
710     WriteOomInfo(processinfo, pid);
711 }
712 
WriteProcesseList(MemoryData & data)713 void MemoryDataPlugin::WriteProcesseList(MemoryData& data)
714 {
715     DIR* procDir = nullptr;
716 
717     procDir = OpenDestDir(testpath_);
718     if (procDir == nullptr) {
719         return;
720     }
721 
722     seenPids_.clear();
723     while (int32_t pid = GetValidPid(procDir)) {
724         addPidBySort(pid);
725     }
726 
727     for (unsigned int i = 0; i < seenPids_.size(); i++) {
728         WriteProcessInfo(data, seenPids_[i]);
729     }
730     closedir(procDir);
731 }
732