106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci#include "io_stats.h" 1606f6ba60Sopenharmony_ci#include "securec.h" 1706f6ba60Sopenharmony_ci 1806f6ba60Sopenharmony_ci#include <sys/types.h> 1906f6ba60Sopenharmony_ci#include <sys/stat.h> 2006f6ba60Sopenharmony_ci#include <fcntl.h> 2106f6ba60Sopenharmony_ci#include <unistd.h> 2206f6ba60Sopenharmony_ci 2306f6ba60Sopenharmony_cinamespace { 2406f6ba60Sopenharmony_ciconst int NUM_ONEHUNDRED = 100; 2506f6ba60Sopenharmony_ciconst double NUM_ZERO_POINTZEROONE = 0.01; 2606f6ba60Sopenharmony_ci#if __DEBUG__ 2706f6ba60Sopenharmony_ciconst char* SYSTIME_PATH = "/data/local/tmp/systimes"; 2806f6ba60Sopenharmony_ciconst char* CPU_PATH = "/data/local/tmp/cpustats"; 2906f6ba60Sopenharmony_ciconst char* DISKSTATS_PATH = "/data/local/tmp/diskstats"; 3006f6ba60Sopenharmony_ciconst int NUM_SEVEN = 7; 3106f6ba60Sopenharmony_ci#else 3206f6ba60Sopenharmony_ciconst char* SYSTIME_PATH = "/proc/uptime"; 3306f6ba60Sopenharmony_ciconst char* CPU_PATH = "/proc/stat"; 3406f6ba60Sopenharmony_ciconst char* DISKSTATS_PATH = "/proc/diskstats"; 3506f6ba60Sopenharmony_ci#endif // #if __DEBUG__ 3606f6ba60Sopenharmony_ciconst int DEC_BASE = 10; 3706f6ba60Sopenharmony_ci} // namespace 3806f6ba60Sopenharmony_ci 3906f6ba60Sopenharmony_ciIoStats::IoStats(DiskioConfig::IoReportType type) : type_(type) 4006f6ba60Sopenharmony_ci{ 4106f6ba60Sopenharmony_ci sysTime_ = GetSystime(); 4206f6ba60Sopenharmony_ci} 4306f6ba60Sopenharmony_ci 4406f6ba60Sopenharmony_ciuint64_t IoStats::GetSystime() 4506f6ba60Sopenharmony_ci{ 4606f6ba60Sopenharmony_ci uint64_t systime = 1; 4706f6ba60Sopenharmony_ci std::ifstream input(SYSTIME_PATH, std::ios::in); 4806f6ba60Sopenharmony_ci CHECK_TRUE(!input.fail(), systime, "%s:open %s failed, errno = %d", __func__, SYSTIME_PATH, errno); 4906f6ba60Sopenharmony_ci do { 5006f6ba60Sopenharmony_ci if (!input.good()) { 5106f6ba60Sopenharmony_ci return systime; 5206f6ba60Sopenharmony_ci } 5306f6ba60Sopenharmony_ci std::string line; 5406f6ba60Sopenharmony_ci getline(input, line); 5506f6ba60Sopenharmony_ci line += '\n'; 5606f6ba60Sopenharmony_ci 5706f6ba60Sopenharmony_ci uint64_t nsec, ncent; 5806f6ba60Sopenharmony_ci if (ParseLineFields(line) > 0) { 5906f6ba60Sopenharmony_ci nsec = fields_[0]; 6006f6ba60Sopenharmony_ci ncent = fields_[1]; 6106f6ba60Sopenharmony_ci systime = nsec * NUM_ONEHUNDRED + ncent; 6206f6ba60Sopenharmony_ci } 6306f6ba60Sopenharmony_ci fields_.clear(); 6406f6ba60Sopenharmony_ci } while (0); 6506f6ba60Sopenharmony_ci input.close(); 6606f6ba60Sopenharmony_ci 6706f6ba60Sopenharmony_ci return systime; 6806f6ba60Sopenharmony_ci} 6906f6ba60Sopenharmony_ci 7006f6ba60Sopenharmony_cibool IoStats::GetIoData() 7106f6ba60Sopenharmony_ci{ 7206f6ba60Sopenharmony_ci ParseCpuStats(); 7306f6ba60Sopenharmony_ci if (type_ == DiskioConfig::IO_REPORT) { 7406f6ba60Sopenharmony_ci ParseIoStats(); 7506f6ba60Sopenharmony_ci } else if (type_ == DiskioConfig::IO_REPORT_EX) { 7606f6ba60Sopenharmony_ci ParseIoStatsEx(); 7706f6ba60Sopenharmony_ci } 7806f6ba60Sopenharmony_ci return true; 7906f6ba60Sopenharmony_ci} 8006f6ba60Sopenharmony_ci 8106f6ba60Sopenharmony_cibool IoStats::ParseCpuStats() 8206f6ba60Sopenharmony_ci{ 8306f6ba60Sopenharmony_ci std::ifstream input(CPU_PATH, std::ios::in); 8406f6ba60Sopenharmony_ci CHECK_TRUE(!input.fail(), false, "%s: open %s failed, errno = %d", __func__, CPU_PATH, errno); 8506f6ba60Sopenharmony_ci do { 8606f6ba60Sopenharmony_ci if (!input.good()) { 8706f6ba60Sopenharmony_ci return false; 8806f6ba60Sopenharmony_ci } 8906f6ba60Sopenharmony_ci std::string line; 9006f6ba60Sopenharmony_ci getline(input, line); 9106f6ba60Sopenharmony_ci 9206f6ba60Sopenharmony_ci auto pos = line.find("cpu"); 9306f6ba60Sopenharmony_ci if (pos != std::string::npos) { 9406f6ba60Sopenharmony_ci line += '\n'; 9506f6ba60Sopenharmony_ci GetCpuStats(line); 9606f6ba60Sopenharmony_ci } 9706f6ba60Sopenharmony_ci } while (!input.eof()); 9806f6ba60Sopenharmony_ci input.close(); 9906f6ba60Sopenharmony_ci 10006f6ba60Sopenharmony_ci return true; 10106f6ba60Sopenharmony_ci} 10206f6ba60Sopenharmony_ci 10306f6ba60Sopenharmony_cibool IoStats::GetCpuStats(std::string& line) 10406f6ba60Sopenharmony_ci{ 10506f6ba60Sopenharmony_ci std::string name; 10606f6ba60Sopenharmony_ci auto cpuData = std::make_shared<ProcStats>(); 10706f6ba60Sopenharmony_ci CHECK_NOTNULL(cpuData, false, "create ProcStats FAILED!"); 10806f6ba60Sopenharmony_ci 10906f6ba60Sopenharmony_ci if (ParseLineFields(line, name) > 0) { 11006f6ba60Sopenharmony_ci int index = 0; 11106f6ba60Sopenharmony_ci cpuData->name_ = name; 11206f6ba60Sopenharmony_ci cpuData->user_ = fields_[index]; 11306f6ba60Sopenharmony_ci index++; 11406f6ba60Sopenharmony_ci cpuData->nice_ = fields_[index]; 11506f6ba60Sopenharmony_ci index++; 11606f6ba60Sopenharmony_ci cpuData->system_ = fields_[index]; 11706f6ba60Sopenharmony_ci index++; 11806f6ba60Sopenharmony_ci cpuData->idle_ = fields_[index]; 11906f6ba60Sopenharmony_ci index++; 12006f6ba60Sopenharmony_ci cpuData->iowait_ = fields_[index]; 12106f6ba60Sopenharmony_ci index++; 12206f6ba60Sopenharmony_ci cpuData->steal_ = fields_[index]; 12306f6ba60Sopenharmony_ci index++; 12406f6ba60Sopenharmony_ci cpuData->hardirq_ = fields_[index]; 12506f6ba60Sopenharmony_ci index++; 12606f6ba60Sopenharmony_ci cpuData->softirq_ = fields_[index]; 12706f6ba60Sopenharmony_ci index++; 12806f6ba60Sopenharmony_ci cpuData->guest_ = fields_[index]; 12906f6ba60Sopenharmony_ci index++; 13006f6ba60Sopenharmony_ci cpuData->guestNice_ = fields_[index]; 13106f6ba60Sopenharmony_ci cpuDatas_.push_back(cpuData); 13206f6ba60Sopenharmony_ci fields_.clear(); 13306f6ba60Sopenharmony_ci return true; 13406f6ba60Sopenharmony_ci } 13506f6ba60Sopenharmony_ci 13606f6ba60Sopenharmony_ci return false; 13706f6ba60Sopenharmony_ci} 13806f6ba60Sopenharmony_ci 13906f6ba60Sopenharmony_cibool IoStats::ParseIoStats() 14006f6ba60Sopenharmony_ci{ 14106f6ba60Sopenharmony_ci std::ifstream input(DISKSTATS_PATH, std::ios::in); 14206f6ba60Sopenharmony_ci CHECK_TRUE(!input.fail(), false, "%s:%d open failed, errno = %d", __func__, __LINE__, errno); 14306f6ba60Sopenharmony_ci do { 14406f6ba60Sopenharmony_ci if (!input.good()) { 14506f6ba60Sopenharmony_ci return false; 14606f6ba60Sopenharmony_ci } 14706f6ba60Sopenharmony_ci std::string line; 14806f6ba60Sopenharmony_ci getline(input, line); 14906f6ba60Sopenharmony_ci line += '\n'; 15006f6ba60Sopenharmony_ci GetIoStats(line); 15106f6ba60Sopenharmony_ci } while (!input.eof()); 15206f6ba60Sopenharmony_ci input.close(); 15306f6ba60Sopenharmony_ci 15406f6ba60Sopenharmony_ci return true; 15506f6ba60Sopenharmony_ci} 15606f6ba60Sopenharmony_ci 15706f6ba60Sopenharmony_cibool IoStats::GetIoStats(std::string& line) 15806f6ba60Sopenharmony_ci{ 15906f6ba60Sopenharmony_ci std::string name; 16006f6ba60Sopenharmony_ci auto ioInfo = std::make_shared<DiskStats>(); 16106f6ba60Sopenharmony_ci CHECK_NOTNULL(ioInfo, false, "create DiskStats FAILED!"); 16206f6ba60Sopenharmony_ci 16306f6ba60Sopenharmony_ci if (ParseLineFields(line, name) > 0) { 16406f6ba60Sopenharmony_ci int index = 0; 16506f6ba60Sopenharmony_ci ioInfo->major_ = fields_[index]; 16606f6ba60Sopenharmony_ci index++; 16706f6ba60Sopenharmony_ci ioInfo->minor_ = fields_[index]; 16806f6ba60Sopenharmony_ci index++; 16906f6ba60Sopenharmony_ci ioInfo->deviceName_ = name; 17006f6ba60Sopenharmony_ci 17106f6ba60Sopenharmony_ci ioInfo->rSucc_ = fields_[index]; 17206f6ba60Sopenharmony_ci index++; 17306f6ba60Sopenharmony_ci ioInfo->rMerged_ = fields_[index]; 17406f6ba60Sopenharmony_ci index++; 17506f6ba60Sopenharmony_ci ioInfo->rSectors_ = fields_[index]; 17606f6ba60Sopenharmony_ci index++; 17706f6ba60Sopenharmony_ci ioInfo->timeOfRead_ = fields_[index]; 17806f6ba60Sopenharmony_ci index++; 17906f6ba60Sopenharmony_ci 18006f6ba60Sopenharmony_ci ioInfo->wSucc_ = fields_[index]; 18106f6ba60Sopenharmony_ci index++; 18206f6ba60Sopenharmony_ci ioInfo->wMerged_ = fields_[index]; 18306f6ba60Sopenharmony_ci index++; 18406f6ba60Sopenharmony_ci ioInfo->wSectors_ = fields_[index]; 18506f6ba60Sopenharmony_ci index++; 18606f6ba60Sopenharmony_ci ioInfo->timeOfWrite_ = fields_[index]; 18706f6ba60Sopenharmony_ci index++; 18806f6ba60Sopenharmony_ci 18906f6ba60Sopenharmony_ci ioInfo->ios_ = fields_[index]; 19006f6ba60Sopenharmony_ci index++; 19106f6ba60Sopenharmony_ci ioInfo->timeOfIo_ = fields_[index]; 19206f6ba60Sopenharmony_ci index++; 19306f6ba60Sopenharmony_ci ioInfo->weighted_ = fields_[index]; 19406f6ba60Sopenharmony_ci index++; 19506f6ba60Sopenharmony_ci 19606f6ba60Sopenharmony_ci ioInfo->dSucc_ = fields_[index]; 19706f6ba60Sopenharmony_ci index++; 19806f6ba60Sopenharmony_ci ioInfo->dMerged_ = fields_[index]; 19906f6ba60Sopenharmony_ci index++; 20006f6ba60Sopenharmony_ci ioInfo->dSectors_ = fields_[index]; 20106f6ba60Sopenharmony_ci index++; 20206f6ba60Sopenharmony_ci ioInfo->timeOfd_ = fields_[index]; 20306f6ba60Sopenharmony_ci index++; 20406f6ba60Sopenharmony_ci 20506f6ba60Sopenharmony_ci ioInfo->flushSucc_ = fields_[index]; 20606f6ba60Sopenharmony_ci index++; 20706f6ba60Sopenharmony_ci ioInfo->timeOfFlush_ = fields_[index]; 20806f6ba60Sopenharmony_ci 20906f6ba60Sopenharmony_ci ioDatas_.push_back(ioInfo); 21006f6ba60Sopenharmony_ci fields_.clear(); 21106f6ba60Sopenharmony_ci return true; 21206f6ba60Sopenharmony_ci } 21306f6ba60Sopenharmony_ci#if __DEBUG__ 21406f6ba60Sopenharmony_ci char debugName[128]; 21506f6ba60Sopenharmony_ci uint64_t rMergesOrIo = 0; 21606f6ba60Sopenharmony_ci uint64_t rwIos = 0; 21706f6ba60Sopenharmony_ci uint64_t rTicksOrw = 0; 21806f6ba60Sopenharmony_ci auto debugIoInfo = std::make_shared<DiskStats>(); 21906f6ba60Sopenharmony_ci int ret = sscanf_s(line.c_str(), "%u %u %s %lu %lu %lu %" PRIu64 " %lu %lu %lu %u %u %u %u %lu %lu %lu %u %lu %u", 22006f6ba60Sopenharmony_ci &debugIoInfo->major_, &debugIoInfo->minor_, debugName, sizeof(debugName), 22106f6ba60Sopenharmony_ci &debugIoInfo->rSucc_, &rMergesOrIo, &rwIos, &rTicksOrw, 22206f6ba60Sopenharmony_ci &debugIoInfo->wSucc_, &debugIoInfo->wMerged_, 22306f6ba60Sopenharmony_ci &debugIoInfo->wSectors_, &debugIoInfo->timeOfWrite_, 22406f6ba60Sopenharmony_ci &debugIoInfo->ios_, &debugIoInfo->timeOfIo_, &debugIoInfo->weighted_, 22506f6ba60Sopenharmony_ci &debugIoInfo->dSucc_, &debugIoInfo->dMerged_, 22606f6ba60Sopenharmony_ci &debugIoInfo->dSectors_, &debugIoInfo->timeOfd_, 22706f6ba60Sopenharmony_ci &debugIoInfo->flushSucc_, &debugIoInfo->timeOfFlush_); 22806f6ba60Sopenharmony_ci if (ret == NUM_SEVEN) { 22906f6ba60Sopenharmony_ci debugIoInfo->rSectors_ = rMergesOrIo; 23006f6ba60Sopenharmony_ci debugIoInfo->wSucc_ = rwIos; 23106f6ba60Sopenharmony_ci debugIoInfo->wSectors_ = rTicksOrw; 23206f6ba60Sopenharmony_ci } else { 23306f6ba60Sopenharmony_ci debugIoInfo->rMerged_ = rMergesOrIo; 23406f6ba60Sopenharmony_ci debugIoInfo->rSectors_ = rwIos; 23506f6ba60Sopenharmony_ci debugIoInfo->timeOfRead_ = rTicksOrw; 23606f6ba60Sopenharmony_ci } 23706f6ba60Sopenharmony_ci debugIoInfo->deviceName_ = std::string(name); 23806f6ba60Sopenharmony_ci ioDatas_.push_back(debugIoInfo); 23906f6ba60Sopenharmony_ci#endif 24006f6ba60Sopenharmony_ci 24106f6ba60Sopenharmony_ci return false; 24206f6ba60Sopenharmony_ci} 24306f6ba60Sopenharmony_ci 24406f6ba60Sopenharmony_cibool IoStats::ParseIoStatsEx() 24506f6ba60Sopenharmony_ci{ 24606f6ba60Sopenharmony_ci return true; 24706f6ba60Sopenharmony_ci} 24806f6ba60Sopenharmony_ci 24906f6ba60Sopenharmony_cidouble IoStats::KeepTowDigits(const uint64_t& data, uint64_t div) 25006f6ba60Sopenharmony_ci{ 25106f6ba60Sopenharmony_ci double result = 0.00; 25206f6ba60Sopenharmony_ci if (data <= 0 || div == 0) { 25306f6ba60Sopenharmony_ci return result; 25406f6ba60Sopenharmony_ci } 25506f6ba60Sopenharmony_ci double ddiv = div; 25606f6ba60Sopenharmony_ci if (ddiv != NUM_TWO) { 25706f6ba60Sopenharmony_ci ddiv = div * NUM_ZERO_POINTZEROONE; 25806f6ba60Sopenharmony_ci } 25906f6ba60Sopenharmony_ci result = static_cast<double>(data) / ddiv; 26006f6ba60Sopenharmony_ci return result; 26106f6ba60Sopenharmony_ci} 26206f6ba60Sopenharmony_ci 26306f6ba60Sopenharmony_cibool IoStats::FindFirstNum(char** p) 26406f6ba60Sopenharmony_ci{ 26506f6ba60Sopenharmony_ci CHECK_NOTNULL(*p, false, "IoStats:%s", __func__); 26606f6ba60Sopenharmony_ci while (**p > '9' || **p < '0') { 26706f6ba60Sopenharmony_ci if (**p == '\0' || **p == '\n') { 26806f6ba60Sopenharmony_ci return false; 26906f6ba60Sopenharmony_ci } 27006f6ba60Sopenharmony_ci (*p)++; 27106f6ba60Sopenharmony_ci } 27206f6ba60Sopenharmony_ci return true; 27306f6ba60Sopenharmony_ci} 27406f6ba60Sopenharmony_ci 27506f6ba60Sopenharmony_cibool IoStats::RemoveSpaces(char** p) 27606f6ba60Sopenharmony_ci{ 27706f6ba60Sopenharmony_ci CHECK_NOTNULL(*p, false, "IoStats:%s", __func__); 27806f6ba60Sopenharmony_ci if (**p == '\0' || **p == '\n') { 27906f6ba60Sopenharmony_ci return false; 28006f6ba60Sopenharmony_ci } 28106f6ba60Sopenharmony_ci while (**p == ' ') { 28206f6ba60Sopenharmony_ci (*p)++; 28306f6ba60Sopenharmony_ci if (**p == '\0' || **p == '\n') { 28406f6ba60Sopenharmony_ci return false; 28506f6ba60Sopenharmony_ci } 28606f6ba60Sopenharmony_ci } 28706f6ba60Sopenharmony_ci return true; 28806f6ba60Sopenharmony_ci} 28906f6ba60Sopenharmony_ci 29006f6ba60Sopenharmony_ciuint32_t IoStats::ParseLineFields(const std::string& line, std::string& name) 29106f6ba60Sopenharmony_ci{ 29206f6ba60Sopenharmony_ci uint64_t num; 29306f6ba60Sopenharmony_ci uint32_t count = 0; 29406f6ba60Sopenharmony_ci char* end = nullptr; 29506f6ba60Sopenharmony_ci char* pTmp = const_cast<char*>(line.c_str()); 29606f6ba60Sopenharmony_ci 29706f6ba60Sopenharmony_ci fields_.clear(); 29806f6ba60Sopenharmony_ci while (pTmp != nullptr && *pTmp != '\n') { 29906f6ba60Sopenharmony_ci CHECK_TRUE(RemoveSpaces(&pTmp), count, "%s: RemoveSpaces failed!", __func__); 30006f6ba60Sopenharmony_ci if (*pTmp >= 'a' && *pTmp <= 'z') { 30106f6ba60Sopenharmony_ci char field[64]; 30206f6ba60Sopenharmony_ci int len = 0; 30306f6ba60Sopenharmony_ci int ret = sscanf_s(pTmp, "%63s %n", field, sizeof(field), &len); 30406f6ba60Sopenharmony_ci if (ret == 1 && *field) { 30506f6ba60Sopenharmony_ci name = std::string(field, strlen(field)); 30606f6ba60Sopenharmony_ci pTmp += len; 30706f6ba60Sopenharmony_ci } 30806f6ba60Sopenharmony_ci } 30906f6ba60Sopenharmony_ci CHECK_TRUE(FindFirstNum(&pTmp), count, "%s: FindFirstNum failed", __func__); 31006f6ba60Sopenharmony_ci num = strtoull(pTmp, &end, DEC_BASE); 31106f6ba60Sopenharmony_ci CHECK_TRUE(num >= 0, count, "%s:strtoull failed", __func__); 31206f6ba60Sopenharmony_ci fields_.push_back(num); 31306f6ba60Sopenharmony_ci pTmp = end; 31406f6ba60Sopenharmony_ci count++; 31506f6ba60Sopenharmony_ci } 31606f6ba60Sopenharmony_ci return count; 31706f6ba60Sopenharmony_ci} 31806f6ba60Sopenharmony_ci 31906f6ba60Sopenharmony_ciuint32_t IoStats::ParseLineFields(const std::string& line) 32006f6ba60Sopenharmony_ci{ 32106f6ba60Sopenharmony_ci uint64_t num; 32206f6ba60Sopenharmony_ci uint32_t count = 0; 32306f6ba60Sopenharmony_ci char* end = nullptr; 32406f6ba60Sopenharmony_ci char* pTmp = const_cast<char*>(line.c_str()); 32506f6ba60Sopenharmony_ci 32606f6ba60Sopenharmony_ci while (pTmp != nullptr && *pTmp != '\n') { 32706f6ba60Sopenharmony_ci CHECK_TRUE(FindFirstNum(&pTmp), count, "%s: FindFirstNum failed", __func__); 32806f6ba60Sopenharmony_ci num = static_cast<uint32_t>(strtoull(pTmp, &end, DEC_BASE)); 32906f6ba60Sopenharmony_ci CHECK_TRUE(num >= 0, count, "%s:strtoull failed", __func__); 33006f6ba60Sopenharmony_ci fields_.push_back(num); 33106f6ba60Sopenharmony_ci pTmp = end; 33206f6ba60Sopenharmony_ci count++; 33306f6ba60Sopenharmony_ci } 33406f6ba60Sopenharmony_ci return count; 33506f6ba60Sopenharmony_ci}