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