1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_IMPL_H_
18 #define SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_IMPL_H_
19 
20 #include <sqlite3.h>
21 #include <atomic>
22 #include <functional>
23 #include <memory>
24 #include <vector>
25 
26 #include "perfetto/base/string_view.h"
27 #include "perfetto/trace_processor/basic_types.h"
28 #include "perfetto/trace_processor/trace_processor.h"
29 #include "src/trace_processor/scoped_db.h"
30 #include "src/trace_processor/trace_processor_context.h"
31 
32 namespace perfetto {
33 
34 namespace trace_processor {
35 
36 enum TraceType {
37   kUnknownTraceType,
38   kProtoTraceType,
39   kProtoWithTrackEventsTraceType,
40   kJsonTraceType,
41   kFuchsiaTraceType,
42 };
43 
44 TraceType GuessTraceType(const uint8_t* data, size_t size);
45 
46 // Coordinates the loading of traces from an arbitrary source and allows
47 // execution of SQL queries on the events in these traces.
48 class TraceProcessorImpl : public TraceProcessor {
49  public:
50   explicit TraceProcessorImpl(const Config&);
51 
52   ~TraceProcessorImpl() override;
53 
54   bool Parse(std::unique_ptr<uint8_t[]>, size_t) override;
55 
56   void NotifyEndOfFile() override;
57 
58   Iterator ExecuteQuery(const std::string& sql,
59                         int64_t time_queued = 0) override;
60 
61   int ComputeMetric(const std::vector<std::string>& metric_names,
62                     std::vector<uint8_t>* metrics) override;
63 
64   void InterruptQuery() override;
65 
66  private:
67   // Needed for iterators to be able to delete themselves from the vector.
68   friend class IteratorImpl;
69 
70   ScopedDb db_;  // Keep first.
71   TraceProcessorContext context_;
72   bool unrecoverable_parse_error_ = false;
73 
74   std::vector<IteratorImpl*> iterators_;
75 
76   // This is atomic because it is set by the CTRL-C signal handler and we need
77   // to prevent single-flow compiler optimizations in ExecuteQuery().
78   std::atomic<bool> query_interrupted_{false};
79 
80   const Config cfg_;
81 };
82 
83 // The pointer implementation of TraceProcessor::Iterator.
84 class TraceProcessor::IteratorImpl {
85  public:
86   IteratorImpl(TraceProcessorImpl* impl,
87                sqlite3* db,
88                ScopedStmt,
89                uint32_t column_count,
90                base::Optional<std::string> error,
91                uint32_t sql_stats_row);
92   ~IteratorImpl();
93 
94   IteratorImpl(IteratorImpl&) noexcept = delete;
95   IteratorImpl& operator=(IteratorImpl&) = delete;
96 
97   IteratorImpl(IteratorImpl&&) noexcept = default;
98   IteratorImpl& operator=(IteratorImpl&&) = default;
99 
100   // Methods called by TraceProcessor::Iterator.
Next()101   bool Next() {
102     // Delegate to the cc file to prevent trace_storage.h include in this
103     // file.
104     if (!called_next_) {
105       RecordFirstNextInSqlStats();
106       called_next_ = true;
107     }
108 
109     if (PERFETTO_UNLIKELY(error_.has_value()))
110       return false;
111 
112     int ret = sqlite3_step(*stmt_);
113     if (PERFETTO_UNLIKELY(ret != SQLITE_ROW && ret != SQLITE_DONE)) {
114       error_ = base::Optional<std::string>(sqlite3_errmsg(db_));
115       return false;
116     }
117     return ret == SQLITE_ROW;
118   }
119 
Get(uint32_t col)120   SqlValue Get(uint32_t col) {
121     auto column = static_cast<int>(col);
122     auto col_type = sqlite3_column_type(*stmt_, column);
123     SqlValue value;
124     switch (col_type) {
125       case SQLITE_INTEGER:
126         value.type = SqlValue::kLong;
127         value.long_value = sqlite3_column_int64(*stmt_, column);
128         break;
129       case SQLITE_TEXT:
130         value.type = SqlValue::kString;
131         value.string_value =
132             reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, column));
133         break;
134       case SQLITE_FLOAT:
135         value.type = SqlValue::kDouble;
136         value.double_value = sqlite3_column_double(*stmt_, column);
137         break;
138       case SQLITE_NULL:
139         value.type = SqlValue::kNull;
140         break;
141     }
142     return value;
143   }
144 
GetColumnName(uint32_t col)145   std::string GetColumnName(uint32_t col) {
146     return sqlite3_column_name(stmt_.get(), static_cast<int>(col));
147   }
148 
ColumnCount()149   uint32_t ColumnCount() { return column_count_; }
150 
GetLastError()151   base::Optional<std::string> GetLastError() { return error_; }
152 
153   // Methods called by TraceProcessorImpl.
154   void Reset();
155 
156  private:
157   void RecordFirstNextInSqlStats();
158 
159   TraceProcessorImpl* trace_processor_;
160   sqlite3* db_ = nullptr;
161   ScopedStmt stmt_;
162   uint32_t column_count_ = 0;
163   base::Optional<std::string> error_;
164 
165   uint32_t sql_stats_row_ = 0;
166   bool called_next_ = false;
167 };
168 
169 }  // namespace trace_processor
170 }  // namespace perfetto
171 
172 #endif  // SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_IMPL_H_
173