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 "segment_analysis.h"
16
17 #include <fcntl.h>
18 #include <unistd.h>
19
20 #include "file_util.h"
21 #include "log_util.h"
22 #include "logger.h"
23 #include "string_util.h"
24 using namespace std;
25 namespace OHOS {
26 namespace HiviewDFX {
27 DEFINE_LOG_TAG("SegmentAnalysis");
~SegmentAnalysis()28 SegmentAnalysis::~SegmentAnalysis()
29 {
30 errLogBuf_.str("");
31 }
32
Analyze(const string & logFile,const ParamFeature & feature,const vector<string> & startSeg,const vector<string> & segStackMatch)33 bool SegmentAnalysis::Analyze(const string& logFile, const ParamFeature& feature,
34 const vector<string>& startSeg, const vector<string>& segStackMatch)
35 {
36 if (!CheckParam(feature, startSeg)) {
37 HIVIEW_LOGE("logFile: %{public}s, CheckParam failed", logFile.c_str());
38 return false;
39 }
40 HIVIEW_LOGI("logFile: %{public}s, feature size: %{public}zu, startSeg: %{public}s",
41 logFile.c_str(), feature.size(), startSeg[0].c_str());
42 if (segMap_.size() == 0) {
43 RecordLayerOneSegment(feature);
44 }
45 if (!GetStartSegment(startSeg) || startSeg_ == nullptr) {
46 HIVIEW_LOGE("Failed to get any segment, segMap_ size: %{public}zu\n", segMap_.size());
47 return false;
48 }
49 if (!LogUtil::ReadFileBuff(logFile, errLogBuf_)) {
50 HIVIEW_LOGE("read logFile: %{public}s failed\n", logFile.c_str());
51 return false;
52 }
53 if (NeedAnalyzeBlockedChain()) {
54 AnalyzeBlockedChain();
55 GetBlockedChain();
56 }
57 GetEndStack(segStackMatch);
58 return true;
59 }
60
GetResult(map<string,string> & result) const61 void SegmentAnalysis::GetResult(map<string, string>& result) const
62 {
63 if (!reason_.empty()) {
64 result[RESULT_REASON] = reason_;
65 }
66 if (!blockedChain_.empty()) {
67 result[RESULT_BLOCKED_CHAIN] = blockedChain_;
68 }
69 if (!allStacks_.empty()) {
70 result[RESULT_ALL_STACKS] = allStacks_;
71 }
72 if (!endStack_.empty()) {
73 result[RESULT_END_STACK] = endStack_;
74 }
75 }
76
AddSegment(int id,UniqSegment & seg)77 void SegmentAnalysis::AddSegment(int id, UniqSegment& seg)
78 {
79 if (id < 0) {
80 HIVIEW_LOGE("segment id invalid: %{public}d", id);
81 return;
82 }
83 idNameVec_.push_back(make_tuple(id, seg->GetName()));
84 segMap_.insert(make_pair(id, move(seg))); // if id already exists, no more update
85 }
86
GetSegment(int id,UniqSegment & seg)87 bool SegmentAnalysis::GetSegment(int id, UniqSegment& seg)
88 {
89 auto it = segMap_.find(id);
90 if (it != segMap_.end()) {
91 seg = move(it->second);
92 segMap_.erase(it); // no need to keep it in the map
93 return true;
94 }
95 return false;
96 }
97
GetNameById(int id) const98 string SegmentAnalysis::GetNameById(int id) const
99 {
100 for (const auto& idName : idNameVec_) {
101 if (get<0>(idName) == id) {
102 return get<1>(idName);
103 }
104 }
105 return string("");
106 }
107
RecordLayerOneSegment(const ParamFeature & feature)108 void SegmentAnalysis::RecordLayerOneSegment(const ParamFeature& feature)
109 {
110 /*
111 * examples of feature:
112 * ("LayerOneCmd.v_id", LineFeature)
113 * ("LayerOneCmd.v_name", LineFeature)
114 * ...
115 * ("LayerOneCmd.v_id", LineFeature)
116 * ("LayerOneCmd.v_name", LineFeature)
117 */
118 auto isFirst = [](const pair<string, LineFeature> &p) {return p.first.find(SEGMENT_CMD_LAYER_ONE) == 0;};
119 auto iter = find_if(begin(feature), end(feature), isFirst);
120 while (iter != end(feature)) {
121 auto nextBegin = iter->first;
122 string value = iter->second.value;
123 auto seg = make_unique<Segment>();
124 seg->SetValue(StringUtil::GetRightSubstr(iter->first, SEGMENT_DELIM), value);
125 seg->SetValue(SEGMENT_CURSOR, to_string(iter->second.lineCursor));
126 for (int i = 1; i < LAYER_ONE_CMD_PARAM_NUM; ++i) {
127 ++iter; // to prevent dead loop
128 if (iter != end(feature) &&
129 iter->first != nextBegin &&
130 iter->first.find(SEGMENT_CMD_LAYER_ONE) == 0) {
131 seg->SetValue(StringUtil::GetRightSubstr(iter->first, SEGMENT_DELIM), iter->second.value);
132 } else {
133 HIVIEW_LOGE("wrong format, nextBegin: %{public}s %{public}s", nextBegin.c_str(), value.c_str());
134 break;
135 }
136 }
137 int id = seg->GetId();
138 AddSegment(id, seg);
139 auto isNext = [&](const pair<string, LineFeature> &p) {return p.first == nextBegin;};
140 auto iterNext = find_if(iter, end(feature), isNext);
141 RecordOtherSegment(feature, id, iter, iterNext);
142 iter = iterNext;
143 }
144 }
145 } // namespace HiviewDFX
146 } // namespace OHOS