Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 516ba989 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "incidentd: parsing ps dump into proto."

parents 1b128eb2 f5cc5759
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -728,6 +728,7 @@ gensrcs {
        "core/proto/android/os/kernelwake.proto",
        "core/proto/android/os/pagetypeinfo.proto",
        "core/proto/android/os/procrank.proto",
        "core/proto/android/os/ps.proto",
        "core/proto/android/os/system_properties.proto",
    ],

+71 −4
Original line number Diff line number Diff line
@@ -52,6 +52,12 @@ static inline std::string trimHeader(const std::string& s) {
    return toLowerStr(trimDefault(s));
}

static inline bool isNumber(const std::string& s) {
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

// This is similiar to Split in android-base/file.h, but it won't add empty string
static void split(const std::string& line, std::vector<std::string>& words,
        const trans_func& func, const std::string& delimiters) {
@@ -86,24 +92,80 @@ record_t parseRecord(const std::string& line, const std::string& delimiters) {
    return record;
}

bool getColumnIndices(std::vector<int>& indices, const char** headerNames, const std::string& line) {
    indices.clear();

    size_t lastIndex = 0;
    int i = 0;
    while (headerNames[i] != NULL) {
        string s = headerNames[i];
        lastIndex = line.find(s, lastIndex);
        if (lastIndex == string::npos) {
            fprintf(stderr, "Bad Task Header: %s\n", line.c_str());
            return false;
        }
        lastIndex += s.length();
        indices.push_back(lastIndex);
        i++;
    }

    return true;
}

record_t parseRecordByColumns(const std::string& line, const std::vector<int>& indices, const std::string& delimiters) {
    record_t record;
    int lastIndex = 0;
    int lastBeginning = 0;
    int lineSize = (int)line.size();
    for (std::vector<int>::const_iterator it = indices.begin(); it != indices.end(); ++it) {
        int idx = *it;
        if (lastIndex > idx || idx > lineSize) {
            record.clear(); // The indices is wrong, return empty;
        if (idx <= lastIndex) {
            // We saved up until lastIndex last time, so we should start at
            // lastIndex + 1 this time.
            idx = lastIndex + 1;
        }
        if (idx > lineSize) {
            if (lastIndex < idx && lastIndex < lineSize) {
                // There's a little bit more for us to save, which we'll do
                // outside of the loop.
                break;
            }
            // If we're past the end of the line AND we've already saved everything up to the end.
            fprintf(stderr, "index wrong: lastIndex: %d, idx: %d, lineSize: %d\n", lastIndex, idx, lineSize);
            record.clear(); // The indices are wrong, return empty.
            return record;
        }
        while (idx < lineSize && delimiters.find(line[idx++]) == std::string::npos);
        record.push_back(trimDefault(line.substr(lastIndex, idx - lastIndex)));
        lastBeginning = lastIndex;
        lastIndex = idx;
    }
    record.push_back(trimDefault(line.substr(lastIndex, lineSize - lastIndex)));
    if (lineSize - lastIndex > 0) {
        int beginning = lastIndex;
        if (record.size() == indices.size()) {
            // We've already encountered all of the columns...put whatever is
            // left in the last column.
            record.pop_back();
            beginning = lastBeginning;
        }
        record.push_back(trimDefault(line.substr(beginning, lineSize - beginning)));
    }
    return record;
}

void printRecord(const record_t& record) {
    fprintf(stderr, "Record: { ");
    if (record.size() == 0) {
        fprintf(stderr, "}\n");
        return;
    }
    for(size_t i = 0; i < record.size(); ++i) {
        if(i != 0) fprintf(stderr, "\", ");
        fprintf(stderr, "\"%s", record[i].c_str());
    }
    fprintf(stderr, "\" }\n");
}

bool stripPrefix(std::string* line, const char* key, bool endAtDelimiter) {
    const auto head = line->find_first_not_of(DEFAULT_WHITESPACE);
    if (head == std::string::npos) return false;
@@ -210,7 +272,10 @@ Table::~Table()
void
Table::addEnumTypeMap(const char* field, const char* enumNames[], const int enumValues[], const int enumSize)
{
    if (mFields.find(field) == mFields.end()) return;
    if (mFields.find(field) == mFields.end()) {
        fprintf(stderr, "Field '%s' not found", string(field).c_str());
        return;
    }

    map<std::string, int> enu;
    for (int i = 0; i < enumSize; i++) {
@@ -268,6 +333,8 @@ Table::insertField(ProtoOutputStream* proto, const std::string& name, const std:
                }
            } else if (mEnumValuesByName.find(value) != mEnumValuesByName.end()) {
                proto->write(found, mEnumValuesByName[value]);
            } else if (isNumber(value)) {
                proto->write(found, toInt(value));
            } else {
                return false;
            }
+11 −0
Original line number Diff line number Diff line
@@ -55,6 +55,14 @@ std::string trim(const std::string& s, const std::string& charset);
header_t parseHeader(const std::string& line, const std::string& delimiters = DEFAULT_WHITESPACE);
record_t parseRecord(const std::string& line, const std::string& delimiters = DEFAULT_WHITESPACE);

/**
 * Gets the list of end indices of each word in the line and places it in the given vector,
 * clearing out the vector beforehand. These indices can be used with parseRecordByColumns.
 * Will return false if there was a problem getting the indices. headerNames
 * must be NULL terminated.
 */
bool getColumnIndices(std::vector<int>& indices, const char* headerNames[], const std::string& line);

/**
 * When a text-format table aligns by its vertical position, it is not possible to split them by purely delimiters.
 * This function allows to parse record by its header's column position' indices, must in ascending order.
@@ -62,6 +70,9 @@ record_t parseRecord(const std::string& line, const std::string& delimiters = DE
 */
record_t parseRecordByColumns(const std::string& line, const std::vector<int>& indices, const std::string& delimiters = DEFAULT_WHITESPACE);

/** Prints record_t to stderr */
void printRecord(const record_t& record);

/**
 * When the line starts/ends with the given key, the function returns true
 * as well as the line argument is changed to the rest trimmed part of the original.
+3 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "parsers/KernelWakesParser.h"
#include "parsers/PageTypeInfoParser.h"
#include "parsers/ProcrankParser.h"
#include "parsers/PsParser.h"
#include "parsers/SystemPropertiesParser.h"

#include <android-base/file.h>
@@ -64,6 +65,8 @@ static TextParserBase* selectParser(int section) {
            return new CpuInfoParser();
        case 2004:
            return new CpuFreqParser();
        case 2005:
            return new PsParser();
        case 2006:
            return new BatteryTypeParser();
        default:
+15 −14
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ CpuInfoParser::Parse(const int in, const int out) const
    vector<int> columnIndices; // task table can't be split by purely delimiter, needs column positions.
    record_t record;
    int nline = 0;
    int diff = 0;
    bool nextToSwap = false;
    bool nextToUsage = false;

@@ -107,19 +108,11 @@ CpuInfoParser::Parse(const int in, const int out) const
            header = parseHeader(line, "[ %]");
            nextToUsage = false;

            // NAME is not in the list since the last split index is default to the end of line.
            const char* headerNames[11] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD" };
            size_t lastIndex = 0;
            for (int i = 0; i < 11; i++) {
                string s = headerNames[i];
                lastIndex = line.find(s, lastIndex);
                if (lastIndex == string::npos) {
                    fprintf(stderr, "Bad Task Header: %s\n", line.c_str());
            // NAME is not in the list since we need to modify the end of the CMD index.
            const char* headerNames[] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD", NULL };
            if (!getColumnIndices(columnIndices, headerNames, line)) {
                return -1;
            }
                lastIndex += s.length();
                columnIndices.push_back(lastIndex);
            }
            // Need to remove the end index of CMD and use the start index of NAME because CMD values contain spaces.
            // for example: ... CMD             NAME
            //              ... Jit thread pool com.google.android.gms.feedback
@@ -128,12 +121,20 @@ CpuInfoParser::Parse(const int in, const int out) const
            int endCMD = columnIndices.back();
            columnIndices.pop_back();
            columnIndices.push_back(line.find("NAME", endCMD) - 1);
            // Add NAME index to complete the column list.
            columnIndices.push_back(columnIndices.back() + 4);
            continue;
        }

        record = parseRecordByColumns(line, columnIndices);
        if (record.size() != header.size()) {
            fprintf(stderr, "[%s]Line %d has missing fields:\n%s\n", this->name.string(), nline, line.c_str());
        diff = record.size() - header.size();
        if (diff < 0) {
            fprintf(stderr, "[%s]Line %d has %d missing fields\n%s\n", this->name.string(), nline, -diff, line.c_str());
            printRecord(record);
            continue;
        } else if (diff > 0) {
            fprintf(stderr, "[%s]Line %d has %d extra fields\n%s\n", this->name.string(), nline, diff, line.c_str());
            printRecord(record);
            continue;
        }

Loading