1*1285115cSWilliam A. Kennington III // Copyright 2021 Google LLC 2*1285115cSWilliam A. Kennington III // 3*1285115cSWilliam A. Kennington III // Licensed under the Apache License, Version 2.0 (the "License"); 4*1285115cSWilliam A. Kennington III // you may not use this file except in compliance with the License. 5*1285115cSWilliam A. Kennington III // You may obtain a copy of the License at 6*1285115cSWilliam A. Kennington III // 7*1285115cSWilliam A. Kennington III // http://www.apache.org/licenses/LICENSE-2.0 8*1285115cSWilliam A. Kennington III // 9*1285115cSWilliam A. Kennington III // Unless required by applicable law or agreed to in writing, software 10*1285115cSWilliam A. Kennington III // distributed under the License is distributed on an "AS IS" BASIS, 11*1285115cSWilliam A. Kennington III // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*1285115cSWilliam A. Kennington III // See the License for the specific language governing permissions and 13*1285115cSWilliam A. Kennington III // limitations under the License. 14*1285115cSWilliam A. Kennington III 15*1285115cSWilliam A. Kennington III #include "metric.hpp" 16*1285115cSWilliam A. Kennington III 17*1285115cSWilliam A. Kennington III #include "metricblob.pb.h" 18*1285115cSWilliam A. Kennington III 19*1285115cSWilliam A. Kennington III #include "util.hpp" 20*1285115cSWilliam A. Kennington III 21*1285115cSWilliam A. Kennington III #include <sys/statvfs.h> 22*1285115cSWilliam A. Kennington III 23*1285115cSWilliam A. Kennington III #include <phosphor-logging/log.hpp> 24*1285115cSWilliam A. Kennington III 25*1285115cSWilliam A. Kennington III #include <cstdint> 26*1285115cSWilliam A. Kennington III #include <filesystem> 27*1285115cSWilliam A. Kennington III #include <sstream> 28*1285115cSWilliam A. Kennington III #include <string> 29*1285115cSWilliam A. Kennington III #include <string_view> 30*1285115cSWilliam A. Kennington III 31*1285115cSWilliam A. Kennington III namespace metric_blob 32*1285115cSWilliam A. Kennington III { 33*1285115cSWilliam A. Kennington III 34*1285115cSWilliam A. Kennington III using phosphor::logging::entry; 35*1285115cSWilliam A. Kennington III using phosphor::logging::log; 36*1285115cSWilliam A. Kennington III using level = phosphor::logging::level; 37*1285115cSWilliam A. Kennington III 38*1285115cSWilliam A. Kennington III BmcHealthSnapshot::BmcHealthSnapshot() : 39*1285115cSWilliam A. Kennington III done(false), stringId(0), ticksPerSec(0) 40*1285115cSWilliam A. Kennington III {} 41*1285115cSWilliam A. Kennington III 42*1285115cSWilliam A. Kennington III struct ProcStatEntry 43*1285115cSWilliam A. Kennington III { 44*1285115cSWilliam A. Kennington III std::string cmdline; 45*1285115cSWilliam A. Kennington III std::string tcomm; 46*1285115cSWilliam A. Kennington III float utime; 47*1285115cSWilliam A. Kennington III float stime; 48*1285115cSWilliam A. Kennington III 49*1285115cSWilliam A. Kennington III // Processes with the longest utime + stime are ranked first. 50*1285115cSWilliam A. Kennington III // Tie breaking is done with cmdline then tcomm. 51*1285115cSWilliam A. Kennington III bool operator<(const ProcStatEntry& other) const 52*1285115cSWilliam A. Kennington III { 53*1285115cSWilliam A. Kennington III const float negTime = -(utime + stime); 54*1285115cSWilliam A. Kennington III const float negOtherTime = -(other.utime + other.stime); 55*1285115cSWilliam A. Kennington III return std::tie(negTime, cmdline, tcomm) < 56*1285115cSWilliam A. Kennington III std::tie(negOtherTime, other.cmdline, other.tcomm); 57*1285115cSWilliam A. Kennington III } 58*1285115cSWilliam A. Kennington III }; 59*1285115cSWilliam A. Kennington III 60*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric BmcHealthSnapshot::getProcStatList() 61*1285115cSWilliam A. Kennington III { 62*1285115cSWilliam A. Kennington III constexpr std::string_view procPath = "/proc/"; 63*1285115cSWilliam A. Kennington III 64*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric ret; 65*1285115cSWilliam A. Kennington III std::vector<ProcStatEntry> entries; 66*1285115cSWilliam A. Kennington III 67*1285115cSWilliam A. Kennington III for (const auto& procEntry : std::filesystem::directory_iterator(procPath)) 68*1285115cSWilliam A. Kennington III { 69*1285115cSWilliam A. Kennington III const std::string& path = procEntry.path(); 70*1285115cSWilliam A. Kennington III int pid = -1; 71*1285115cSWilliam A. Kennington III if (isNumericPath(path, pid)) 72*1285115cSWilliam A. Kennington III { 73*1285115cSWilliam A. Kennington III ProcStatEntry entry; 74*1285115cSWilliam A. Kennington III 75*1285115cSWilliam A. Kennington III try 76*1285115cSWilliam A. Kennington III { 77*1285115cSWilliam A. Kennington III entry.cmdline = getCmdLine(pid); 78*1285115cSWilliam A. Kennington III TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec); 79*1285115cSWilliam A. Kennington III entry.tcomm = t.tcomm; 80*1285115cSWilliam A. Kennington III entry.utime = t.utime; 81*1285115cSWilliam A. Kennington III entry.stime = t.stime; 82*1285115cSWilliam A. Kennington III 83*1285115cSWilliam A. Kennington III entries.push_back(entry); 84*1285115cSWilliam A. Kennington III } 85*1285115cSWilliam A. Kennington III catch (const std::exception& e) 86*1285115cSWilliam A. Kennington III { 87*1285115cSWilliam A. Kennington III log<level::ERR>("Could not obtain process stats"); 88*1285115cSWilliam A. Kennington III } 89*1285115cSWilliam A. Kennington III } 90*1285115cSWilliam A. Kennington III } 91*1285115cSWilliam A. Kennington III 92*1285115cSWilliam A. Kennington III std::sort(entries.begin(), entries.end()); 93*1285115cSWilliam A. Kennington III 94*1285115cSWilliam A. Kennington III bool isOthers = false; 95*1285115cSWilliam A. Kennington III ProcStatEntry others; 96*1285115cSWilliam A. Kennington III others.cmdline = "(Others)"; 97*1285115cSWilliam A. Kennington III others.utime = others.stime = 0; 98*1285115cSWilliam A. Kennington III 99*1285115cSWilliam A. Kennington III // Only show this many processes and aggregate all remaining ones into 100*1285115cSWilliam A. Kennington III // "others" in order to keep the size of the snapshot reasonably small. 101*1285115cSWilliam A. Kennington III // With 10 process stat entries and 10 FD count entries, the size of the 102*1285115cSWilliam A. Kennington III // snapshot reaches around 1.5KiB. This is non-trivial, and we have to set 103*1285115cSWilliam A. Kennington III // the collection interval long enough so as not to over-stress the IPMI 104*1285115cSWilliam A. Kennington III // interface and the data collection service. The value of 10 is chosen 105*1285115cSWilliam A. Kennington III // empirically, it might be subject to adjustments when the system is 106*1285115cSWilliam A. Kennington III // launched later. 107*1285115cSWilliam A. Kennington III constexpr int topN = 10; 108*1285115cSWilliam A. Kennington III 109*1285115cSWilliam A. Kennington III for (size_t i = 0; i < entries.size(); ++i) 110*1285115cSWilliam A. Kennington III { 111*1285115cSWilliam A. Kennington III if (i >= topN) 112*1285115cSWilliam A. Kennington III { 113*1285115cSWilliam A. Kennington III isOthers = true; 114*1285115cSWilliam A. Kennington III } 115*1285115cSWilliam A. Kennington III 116*1285115cSWilliam A. Kennington III ProcStatEntry& entry = entries[i]; 117*1285115cSWilliam A. Kennington III 118*1285115cSWilliam A. Kennington III if (isOthers) 119*1285115cSWilliam A. Kennington III { 120*1285115cSWilliam A. Kennington III others.utime += entry.utime; 121*1285115cSWilliam A. Kennington III others.stime += entry.stime; 122*1285115cSWilliam A. Kennington III } 123*1285115cSWilliam A. Kennington III else 124*1285115cSWilliam A. Kennington III { 125*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric::BmcProcStat s; 126*1285115cSWilliam A. Kennington III std::string fullCmdline = entry.cmdline; 127*1285115cSWilliam A. Kennington III if (entry.tcomm.size() > 0) 128*1285115cSWilliam A. Kennington III { 129*1285115cSWilliam A. Kennington III fullCmdline += " " + entry.tcomm; 130*1285115cSWilliam A. Kennington III } 131*1285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(fullCmdline)); 132*1285115cSWilliam A. Kennington III s.set_utime(entry.utime); 133*1285115cSWilliam A. Kennington III s.set_stime(entry.stime); 134*1285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 135*1285115cSWilliam A. Kennington III } 136*1285115cSWilliam A. Kennington III } 137*1285115cSWilliam A. Kennington III 138*1285115cSWilliam A. Kennington III if (isOthers) 139*1285115cSWilliam A. Kennington III { 140*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric::BmcProcStat s; 141*1285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(others.cmdline)); 142*1285115cSWilliam A. Kennington III s.set_utime(others.utime); 143*1285115cSWilliam A. Kennington III s.set_stime(others.stime); 144*1285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 145*1285115cSWilliam A. Kennington III } 146*1285115cSWilliam A. Kennington III 147*1285115cSWilliam A. Kennington III return ret; 148*1285115cSWilliam A. Kennington III } 149*1285115cSWilliam A. Kennington III 150*1285115cSWilliam A. Kennington III int getFdCount(int pid) 151*1285115cSWilliam A. Kennington III { 152*1285115cSWilliam A. Kennington III const std::string& fdPath = "/proc/" + std::to_string(pid) + "/fd"; 153*1285115cSWilliam A. Kennington III return std::distance(std::filesystem::directory_iterator(fdPath), 154*1285115cSWilliam A. Kennington III std::filesystem::directory_iterator{}); 155*1285115cSWilliam A. Kennington III } 156*1285115cSWilliam A. Kennington III 157*1285115cSWilliam A. Kennington III struct FdStatEntry 158*1285115cSWilliam A. Kennington III { 159*1285115cSWilliam A. Kennington III int fdCount; 160*1285115cSWilliam A. Kennington III std::string cmdline; 161*1285115cSWilliam A. Kennington III std::string tcomm; 162*1285115cSWilliam A. Kennington III 163*1285115cSWilliam A. Kennington III // Processes with the largest fdCount goes first. 164*1285115cSWilliam A. Kennington III // Tie-breaking using cmdline then tcomm. 165*1285115cSWilliam A. Kennington III bool operator<(const FdStatEntry& other) const 166*1285115cSWilliam A. Kennington III { 167*1285115cSWilliam A. Kennington III const int negFdCount = -fdCount; 168*1285115cSWilliam A. Kennington III const int negOtherFdCount = -other.fdCount; 169*1285115cSWilliam A. Kennington III return std::tie(negFdCount, cmdline, tcomm) < 170*1285115cSWilliam A. Kennington III std::tie(negOtherFdCount, other.cmdline, other.tcomm); 171*1285115cSWilliam A. Kennington III } 172*1285115cSWilliam A. Kennington III }; 173*1285115cSWilliam A. Kennington III 174*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric BmcHealthSnapshot::getFdStatList() 175*1285115cSWilliam A. Kennington III { 176*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric ret; 177*1285115cSWilliam A. Kennington III 178*1285115cSWilliam A. Kennington III // Sort by fd count, no tie-breaking 179*1285115cSWilliam A. Kennington III std::vector<FdStatEntry> entries; 180*1285115cSWilliam A. Kennington III 181*1285115cSWilliam A. Kennington III const std::string_view procPath = "/proc/"; 182*1285115cSWilliam A. Kennington III for (const auto& procEntry : std::filesystem::directory_iterator(procPath)) 183*1285115cSWilliam A. Kennington III { 184*1285115cSWilliam A. Kennington III const std::string& path = procEntry.path(); 185*1285115cSWilliam A. Kennington III int pid = 0; 186*1285115cSWilliam A. Kennington III FdStatEntry entry; 187*1285115cSWilliam A. Kennington III if (isNumericPath(path, pid)) 188*1285115cSWilliam A. Kennington III { 189*1285115cSWilliam A. Kennington III try 190*1285115cSWilliam A. Kennington III { 191*1285115cSWilliam A. Kennington III entry.fdCount = getFdCount(pid); 192*1285115cSWilliam A. Kennington III TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec); 193*1285115cSWilliam A. Kennington III entry.cmdline = getCmdLine(pid); 194*1285115cSWilliam A. Kennington III entry.tcomm = t.tcomm; 195*1285115cSWilliam A. Kennington III entries.push_back(entry); 196*1285115cSWilliam A. Kennington III } 197*1285115cSWilliam A. Kennington III catch (const std::exception& e) 198*1285115cSWilliam A. Kennington III { 199*1285115cSWilliam A. Kennington III log<level::ERR>("Could not get file descriptor stats"); 200*1285115cSWilliam A. Kennington III } 201*1285115cSWilliam A. Kennington III } 202*1285115cSWilliam A. Kennington III } 203*1285115cSWilliam A. Kennington III 204*1285115cSWilliam A. Kennington III std::sort(entries.begin(), entries.end()); 205*1285115cSWilliam A. Kennington III 206*1285115cSWilliam A. Kennington III bool isOthers = false; 207*1285115cSWilliam A. Kennington III 208*1285115cSWilliam A. Kennington III // Only report the detailed fd count and cmdline for the top 10 entries, 209*1285115cSWilliam A. Kennington III // and collapse all others into "others". 210*1285115cSWilliam A. Kennington III constexpr int topN = 10; 211*1285115cSWilliam A. Kennington III 212*1285115cSWilliam A. Kennington III FdStatEntry others; 213*1285115cSWilliam A. Kennington III others.cmdline = "(Others)"; 214*1285115cSWilliam A. Kennington III others.fdCount = 0; 215*1285115cSWilliam A. Kennington III 216*1285115cSWilliam A. Kennington III for (size_t i = 0; i < entries.size(); ++i) 217*1285115cSWilliam A. Kennington III { 218*1285115cSWilliam A. Kennington III if (i >= topN) 219*1285115cSWilliam A. Kennington III { 220*1285115cSWilliam A. Kennington III isOthers = true; 221*1285115cSWilliam A. Kennington III } 222*1285115cSWilliam A. Kennington III 223*1285115cSWilliam A. Kennington III const FdStatEntry& entry = entries[i]; 224*1285115cSWilliam A. Kennington III if (isOthers) 225*1285115cSWilliam A. Kennington III { 226*1285115cSWilliam A. Kennington III others.fdCount += entry.fdCount; 227*1285115cSWilliam A. Kennington III } 228*1285115cSWilliam A. Kennington III else 229*1285115cSWilliam A. Kennington III { 230*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric::BmcFdStat s; 231*1285115cSWilliam A. Kennington III std::string fullCmdline = entry.cmdline; 232*1285115cSWilliam A. Kennington III if (entry.tcomm.size() > 0) 233*1285115cSWilliam A. Kennington III { 234*1285115cSWilliam A. Kennington III fullCmdline += " " + entry.tcomm; 235*1285115cSWilliam A. Kennington III } 236*1285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(fullCmdline)); 237*1285115cSWilliam A. Kennington III s.set_fd_count(entry.fdCount); 238*1285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 239*1285115cSWilliam A. Kennington III } 240*1285115cSWilliam A. Kennington III } 241*1285115cSWilliam A. Kennington III 242*1285115cSWilliam A. Kennington III if (isOthers) 243*1285115cSWilliam A. Kennington III { 244*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric::BmcFdStat s; 245*1285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(others.cmdline)); 246*1285115cSWilliam A. Kennington III s.set_fd_count(others.fdCount); 247*1285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 248*1285115cSWilliam A. Kennington III } 249*1285115cSWilliam A. Kennington III 250*1285115cSWilliam A. Kennington III return ret; 251*1285115cSWilliam A. Kennington III } 252*1285115cSWilliam A. Kennington III 253*1285115cSWilliam A. Kennington III void BmcHealthSnapshot::serializeSnapshotToArray( 254*1285115cSWilliam A. Kennington III const bmcmetrics::metricproto::BmcMetricSnapshot& snapshot) 255*1285115cSWilliam A. Kennington III { 256*1285115cSWilliam A. Kennington III size_t size = snapshot.ByteSizeLong(); 257*1285115cSWilliam A. Kennington III if (size > 0) 258*1285115cSWilliam A. Kennington III { 259*1285115cSWilliam A. Kennington III pbDump.resize(size); 260*1285115cSWilliam A. Kennington III if (!snapshot.SerializeToArray(pbDump.data(), size)) 261*1285115cSWilliam A. Kennington III { 262*1285115cSWilliam A. Kennington III log<level::ERR>("Could not serialize protobuf to array"); 263*1285115cSWilliam A. Kennington III } 264*1285115cSWilliam A. Kennington III } 265*1285115cSWilliam A. Kennington III } 266*1285115cSWilliam A. Kennington III 267*1285115cSWilliam A. Kennington III void BmcHealthSnapshot::doWork() 268*1285115cSWilliam A. Kennington III { 269*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcMetricSnapshot snapshot; 270*1285115cSWilliam A. Kennington III 271*1285115cSWilliam A. Kennington III // Memory info 272*1285115cSWilliam A. Kennington III std::string meminfoBuffer = readFileIntoString("/proc/meminfo"); 273*1285115cSWilliam A. Kennington III 274*1285115cSWilliam A. Kennington III { 275*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcMemoryMetric m; 276*1285115cSWilliam A. Kennington III 277*1285115cSWilliam A. Kennington III std::string_view sv(meminfoBuffer.data()); 278*1285115cSWilliam A. Kennington III // MemAvailable 279*1285115cSWilliam A. Kennington III int value; 280*1285115cSWilliam A. Kennington III bool ok = parseMeminfoValue(sv, "MemAvailable:", value); 281*1285115cSWilliam A. Kennington III if (ok) 282*1285115cSWilliam A. Kennington III { 283*1285115cSWilliam A. Kennington III m.set_mem_available(value); 284*1285115cSWilliam A. Kennington III } 285*1285115cSWilliam A. Kennington III 286*1285115cSWilliam A. Kennington III ok = parseMeminfoValue(sv, "Slab:", value); 287*1285115cSWilliam A. Kennington III if (ok) 288*1285115cSWilliam A. Kennington III { 289*1285115cSWilliam A. Kennington III m.set_slab(value); 290*1285115cSWilliam A. Kennington III } 291*1285115cSWilliam A. Kennington III 292*1285115cSWilliam A. Kennington III ok = parseMeminfoValue(sv, "KernelStack:", value); 293*1285115cSWilliam A. Kennington III if (ok) 294*1285115cSWilliam A. Kennington III { 295*1285115cSWilliam A. Kennington III m.set_kernel_stack(value); 296*1285115cSWilliam A. Kennington III } 297*1285115cSWilliam A. Kennington III 298*1285115cSWilliam A. Kennington III *(snapshot.mutable_memory_metric()) = m; 299*1285115cSWilliam A. Kennington III } 300*1285115cSWilliam A. Kennington III 301*1285115cSWilliam A. Kennington III // Uptime 302*1285115cSWilliam A. Kennington III std::string uptimeBuffer = readFileIntoString("/proc/uptime"); 303*1285115cSWilliam A. Kennington III double uptime = 0, idleProcessTime = 0; 304*1285115cSWilliam A. Kennington III if (parseProcUptime(uptimeBuffer, uptime, idleProcessTime)) 305*1285115cSWilliam A. Kennington III { 306*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcUptimeMetric m1; 307*1285115cSWilliam A. Kennington III m1.set_uptime(uptime); 308*1285115cSWilliam A. Kennington III m1.set_idle_process_time(idleProcessTime); 309*1285115cSWilliam A. Kennington III *(snapshot.mutable_uptime_metric()) = m1; 310*1285115cSWilliam A. Kennington III } 311*1285115cSWilliam A. Kennington III else 312*1285115cSWilliam A. Kennington III { 313*1285115cSWilliam A. Kennington III log<level::ERR>("Error parsing /proc/uptime"); 314*1285115cSWilliam A. Kennington III } 315*1285115cSWilliam A. Kennington III 316*1285115cSWilliam A. Kennington III // Storage space 317*1285115cSWilliam A. Kennington III struct statvfs fiData; 318*1285115cSWilliam A. Kennington III if ((statvfs("/", &fiData)) < 0) 319*1285115cSWilliam A. Kennington III { 320*1285115cSWilliam A. Kennington III log<level::ERR>("Could not call statvfs"); 321*1285115cSWilliam A. Kennington III } 322*1285115cSWilliam A. Kennington III else 323*1285115cSWilliam A. Kennington III { 324*1285115cSWilliam A. Kennington III uint64_t kib = (fiData.f_bsize * fiData.f_bfree) / 1024; 325*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcDiskSpaceMetric m2; 326*1285115cSWilliam A. Kennington III m2.set_rwfs_kib_available(static_cast<int>(kib)); 327*1285115cSWilliam A. Kennington III *(snapshot.mutable_storage_space_metric()) = m2; 328*1285115cSWilliam A. Kennington III } 329*1285115cSWilliam A. Kennington III 330*1285115cSWilliam A. Kennington III // The next metrics require a sane ticks_per_sec value, typically 100 on 331*1285115cSWilliam A. Kennington III // the BMC. In the very rare circumstance when it's 0, exit early and return 332*1285115cSWilliam A. Kennington III // a partially complete snapshot (no process). 333*1285115cSWilliam A. Kennington III ticksPerSec = getTicksPerSec(); 334*1285115cSWilliam A. Kennington III 335*1285115cSWilliam A. Kennington III // FD stat 336*1285115cSWilliam A. Kennington III *(snapshot.mutable_fdstat_metric()) = getFdStatList(); 337*1285115cSWilliam A. Kennington III 338*1285115cSWilliam A. Kennington III if (ticksPerSec == 0) 339*1285115cSWilliam A. Kennington III { 340*1285115cSWilliam A. Kennington III log<level::ERR>("ticksPerSec is 0, skipping the process list metric"); 341*1285115cSWilliam A. Kennington III serializeSnapshotToArray(snapshot); 342*1285115cSWilliam A. Kennington III done = true; 343*1285115cSWilliam A. Kennington III return; 344*1285115cSWilliam A. Kennington III } 345*1285115cSWilliam A. Kennington III 346*1285115cSWilliam A. Kennington III // Proc stat 347*1285115cSWilliam A. Kennington III *(snapshot.mutable_procstat_metric()) = getProcStatList(); 348*1285115cSWilliam A. Kennington III 349*1285115cSWilliam A. Kennington III // String table 350*1285115cSWilliam A. Kennington III std::vector<std::string_view> strings(stringTable.size()); 351*1285115cSWilliam A. Kennington III for (const auto& [s, i] : stringTable) 352*1285115cSWilliam A. Kennington III { 353*1285115cSWilliam A. Kennington III strings[i] = s; 354*1285115cSWilliam A. Kennington III } 355*1285115cSWilliam A. Kennington III 356*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcStringTable st; 357*1285115cSWilliam A. Kennington III for (size_t i = 0; i < strings.size(); ++i) 358*1285115cSWilliam A. Kennington III { 359*1285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcStringTable::StringEntry entry; 360*1285115cSWilliam A. Kennington III entry.set_value(strings[i].data()); 361*1285115cSWilliam A. Kennington III *(st.add_entries()) = entry; 362*1285115cSWilliam A. Kennington III } 363*1285115cSWilliam A. Kennington III *(snapshot.mutable_string_table()) = st; 364*1285115cSWilliam A. Kennington III 365*1285115cSWilliam A. Kennington III // Save to buffer 366*1285115cSWilliam A. Kennington III serializeSnapshotToArray(snapshot); 367*1285115cSWilliam A. Kennington III done = true; 368*1285115cSWilliam A. Kennington III } 369*1285115cSWilliam A. Kennington III 370*1285115cSWilliam A. Kennington III // BmcBlobSessionStat (9) but passing meta as reference instead of pointer, 371*1285115cSWilliam A. Kennington III // since the metadata must not be null at this point. 372*1285115cSWilliam A. Kennington III bool BmcHealthSnapshot::stat(blobs::BlobMeta& meta) 373*1285115cSWilliam A. Kennington III { 374*1285115cSWilliam A. Kennington III if (!done) 375*1285115cSWilliam A. Kennington III { 376*1285115cSWilliam A. Kennington III // Bits 8~15 are blob-specific state flags. 377*1285115cSWilliam A. Kennington III // For this blob, bit 8 is set when metric collection is still in 378*1285115cSWilliam A. Kennington III // progress. 379*1285115cSWilliam A. Kennington III meta.blobState |= (1 << 8); 380*1285115cSWilliam A. Kennington III } 381*1285115cSWilliam A. Kennington III else 382*1285115cSWilliam A. Kennington III { 383*1285115cSWilliam A. Kennington III meta.blobState = 0; 384*1285115cSWilliam A. Kennington III meta.blobState = blobs::StateFlags::open_read; 385*1285115cSWilliam A. Kennington III meta.size = pbDump.size(); 386*1285115cSWilliam A. Kennington III } 387*1285115cSWilliam A. Kennington III return true; 388*1285115cSWilliam A. Kennington III } 389*1285115cSWilliam A. Kennington III 390*1285115cSWilliam A. Kennington III std::string_view BmcHealthSnapshot::read(uint32_t offset, 391*1285115cSWilliam A. Kennington III uint32_t requestedSize) 392*1285115cSWilliam A. Kennington III { 393*1285115cSWilliam A. Kennington III uint32_t size = static_cast<uint32_t>(pbDump.size()); 394*1285115cSWilliam A. Kennington III if (offset >= size) 395*1285115cSWilliam A. Kennington III { 396*1285115cSWilliam A. Kennington III return {}; 397*1285115cSWilliam A. Kennington III } 398*1285115cSWilliam A. Kennington III return std::string_view(pbDump.data() + offset, 399*1285115cSWilliam A. Kennington III std::min(requestedSize, size - offset)); 400*1285115cSWilliam A. Kennington III } 401*1285115cSWilliam A. Kennington III 402*1285115cSWilliam A. Kennington III int BmcHealthSnapshot::getStringID(const std::string_view s) 403*1285115cSWilliam A. Kennington III { 404*1285115cSWilliam A. Kennington III int ret = 0; 405*1285115cSWilliam A. Kennington III auto itr = stringTable.find(s.data()); 406*1285115cSWilliam A. Kennington III if (itr == stringTable.end()) 407*1285115cSWilliam A. Kennington III { 408*1285115cSWilliam A. Kennington III stringTable[s.data()] = stringId; 409*1285115cSWilliam A. Kennington III ret = stringId; 410*1285115cSWilliam A. Kennington III ++stringId; 411*1285115cSWilliam A. Kennington III } 412*1285115cSWilliam A. Kennington III else 413*1285115cSWilliam A. Kennington III { 414*1285115cSWilliam A. Kennington III ret = itr->second; 415*1285115cSWilliam A. Kennington III } 416*1285115cSWilliam A. Kennington III return ret; 417*1285115cSWilliam A. Kennington III } 418*1285115cSWilliam A. Kennington III 419*1285115cSWilliam A. Kennington III } // namespace metric_blob