1 /* 2 * Copyright (C) 2020 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_ITERATOR_IMPL_H_ 18 #define SRC_TRACE_PROCESSOR_ITERATOR_IMPL_H_ 19 20 #include <sqlite3.h> 21 22 #include <memory> 23 #include <vector> 24 25 #include "perfetto/base/build_config.h" 26 #include "perfetto/base/export.h" 27 #include "perfetto/trace_processor/basic_types.h" 28 #include "perfetto/trace_processor/iterator.h" 29 #include "perfetto/trace_processor/status.h" 30 #include "src/trace_processor/sqlite/scoped_db.h" 31 32 namespace perfetto { 33 namespace trace_processor { 34 35 class TraceProcessorImpl; 36 37 class IteratorImpl { 38 public: 39 IteratorImpl(TraceProcessorImpl* impl, 40 sqlite3* db, 41 ScopedStmt, 42 uint32_t column_count, 43 util::Status, 44 uint32_t sql_stats_row); 45 ~IteratorImpl(); 46 47 IteratorImpl(IteratorImpl&) noexcept = delete; 48 IteratorImpl& operator=(IteratorImpl&) = delete; 49 50 IteratorImpl(IteratorImpl&&) noexcept = default; 51 IteratorImpl& operator=(IteratorImpl&&) = default; 52 53 // Methods called by the base Iterator class. Next()54 bool Next() { 55 // Delegate to the cc file to prevent trace_storage.h include in this file. 56 if (!called_next_) { 57 RecordFirstNextInSqlStats(); 58 called_next_ = true; 59 } 60 61 if (!status_.ok()) 62 return false; 63 64 int ret = sqlite3_step(*stmt_); 65 if (PERFETTO_UNLIKELY(ret != SQLITE_ROW && ret != SQLITE_DONE)) { 66 status_ = util::ErrStatus("%s", sqlite3_errmsg(db_)); 67 return false; 68 } 69 return ret == SQLITE_ROW; 70 } 71 Get(uint32_t col)72 SqlValue Get(uint32_t col) { 73 auto column = static_cast<int>(col); 74 auto col_type = sqlite3_column_type(*stmt_, column); 75 SqlValue value; 76 switch (col_type) { 77 case SQLITE_INTEGER: 78 value.type = SqlValue::kLong; 79 value.long_value = sqlite3_column_int64(*stmt_, column); 80 break; 81 case SQLITE_TEXT: 82 value.type = SqlValue::kString; 83 value.string_value = 84 reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, column)); 85 break; 86 case SQLITE_FLOAT: 87 value.type = SqlValue::kDouble; 88 value.double_value = sqlite3_column_double(*stmt_, column); 89 break; 90 case SQLITE_BLOB: 91 value.type = SqlValue::kBytes; 92 value.bytes_value = sqlite3_column_blob(*stmt_, column); 93 value.bytes_count = 94 static_cast<size_t>(sqlite3_column_bytes(*stmt_, column)); 95 break; 96 case SQLITE_NULL: 97 value.type = SqlValue::kNull; 98 break; 99 } 100 return value; 101 } 102 GetColumnName(uint32_t col)103 std::string GetColumnName(uint32_t col) { 104 return sqlite3_column_name(stmt_.get(), static_cast<int>(col)); 105 } 106 ColumnCount()107 uint32_t ColumnCount() { return column_count_; } 108 Status()109 util::Status Status() { return status_; } 110 111 private: 112 // Dummy function to pass to ScopedResource. DummyClose(TraceProcessorImpl *)113 static int DummyClose(TraceProcessorImpl*) { return 0; } 114 115 // Iterators hold onto an instance of TraceProcessor to track when the query 116 // ends in the sql stats table. As iterators are movable, we need to null out 117 // the TraceProcessor in the moved out iterator to avoid double recording 118 // query ends. We could manually define a move constructor instead, but given 119 // the error prone nature of keeping functions up to date, this seems like a 120 // nicer approach. 121 using ScopedTraceProcessor = 122 base::ScopedResource<TraceProcessorImpl*, &DummyClose, nullptr>; 123 124 void RecordFirstNextInSqlStats(); 125 126 ScopedTraceProcessor trace_processor_; 127 sqlite3* db_ = nullptr; 128 ScopedStmt stmt_; 129 uint32_t column_count_ = 0; 130 util::Status status_; 131 132 uint32_t sql_stats_row_ = 0; 133 bool called_next_ = false; 134 }; 135 136 } // namespace trace_processor 137 } // namespace perfetto 138 139 #endif // SRC_TRACE_PROCESSOR_ITERATOR_IMPL_H_ 140