• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "src/trace_processor/sqlite/stats_table.h"
18 
19 #include "perfetto/base/status.h"
20 #include "src/trace_processor/sqlite/sqlite_utils.h"
21 
22 namespace perfetto {
23 namespace trace_processor {
24 
StatsTable(sqlite3 *,const TraceStorage * storage)25 StatsTable::StatsTable(sqlite3*, const TraceStorage* storage)
26     : storage_(storage) {}
27 
28 StatsTable::~StatsTable() = default;
29 
Init(int,const char * const *,Schema * schema)30 util::Status StatsTable::Init(int, const char* const*, Schema* schema) {
31   *schema = Schema(
32       {
33           SqliteTable::Column(Column::kName, "name", SqlValue::Type::kString),
34           // Calling a column "index" causes sqlite to silently fail, hence idx.
35           SqliteTable::Column(Column::kIndex, "idx", SqlValue::Type::kLong),
36           SqliteTable::Column(Column::kSeverity, "severity",
37                               SqlValue::Type::kString),
38           SqliteTable::Column(Column::kSource, "source",
39                               SqlValue::Type::kString),
40           SqliteTable::Column(Column::kValue, "value", SqlValue::Type::kLong),
41           SqliteTable::Column(Column::kDescription, "description",
42                               SqlValue::Type::kString),
43       },
44       {Column::kName});
45   return util::OkStatus();
46 }
47 
CreateCursor()48 std::unique_ptr<SqliteTable::BaseCursor> StatsTable::CreateCursor() {
49   return std::unique_ptr<SqliteTable::BaseCursor>(new Cursor(this));
50 }
51 
BestIndex(const QueryConstraints &,BestIndexInfo *)52 int StatsTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
53   return SQLITE_OK;
54 }
55 
Cursor(StatsTable * table)56 StatsTable::Cursor::Cursor(StatsTable* table)
57     : SqliteTable::BaseCursor(table),
58       table_(table),
59       storage_(table->storage_) {}
60 
61 StatsTable::Cursor::~Cursor() = default;
62 
Filter(const QueryConstraints &,sqlite3_value **,FilterHistory)63 base::Status StatsTable::Cursor::Filter(const QueryConstraints&,
64                                         sqlite3_value**,
65                                         FilterHistory) {
66   *this = Cursor(table_);
67   return base::OkStatus();
68 }
69 
Column(sqlite3_context * ctx,int N)70 base::Status StatsTable::Cursor::Column(sqlite3_context* ctx, int N) {
71   const auto kSqliteStatic = sqlite_utils::kSqliteStatic;
72   switch (N) {
73     case Column::kName:
74       sqlite3_result_text(ctx, stats::kNames[key_], -1, kSqliteStatic);
75       break;
76     case Column::kIndex:
77       if (stats::kTypes[key_] == stats::kIndexed) {
78         sqlite3_result_int(ctx, index_->first);
79       } else {
80         sqlite3_result_null(ctx);
81       }
82       break;
83     case Column::kSeverity:
84       switch (stats::kSeverities[key_]) {
85         case stats::kInfo:
86           sqlite3_result_text(ctx, "info", -1, kSqliteStatic);
87           break;
88         case stats::kDataLoss:
89           sqlite3_result_text(ctx, "data_loss", -1, kSqliteStatic);
90           break;
91         case stats::kError:
92           sqlite3_result_text(ctx, "error", -1, kSqliteStatic);
93           break;
94       }
95       break;
96     case Column::kSource:
97       switch (stats::kSources[key_]) {
98         case stats::kTrace:
99           sqlite3_result_text(ctx, "trace", -1, kSqliteStatic);
100           break;
101         case stats::kAnalysis:
102           sqlite3_result_text(ctx, "analysis", -1, kSqliteStatic);
103           break;
104       }
105       break;
106     case Column::kValue:
107       if (stats::kTypes[key_] == stats::kIndexed) {
108         sqlite3_result_int64(ctx, index_->second);
109       } else {
110         sqlite3_result_int64(ctx, storage_->stats()[key_].value);
111       }
112       break;
113     case Column::kDescription:
114       sqlite3_result_text(ctx, stats::kDescriptions[key_], -1, kSqliteStatic);
115       break;
116     default:
117       PERFETTO_FATAL("Unknown column %d", N);
118       break;
119   }
120   return base::OkStatus();
121 }
122 
Next()123 base::Status StatsTable::Cursor::Next() {
124   static_assert(stats::kTypes[0] == stats::kSingle,
125                 "the first stats entry cannot be indexed");
126   const auto* cur_entry = &storage_->stats()[key_];
127   if (stats::kTypes[key_] == stats::kIndexed) {
128     if (++index_ != cur_entry->indexed_values.end()) {
129       return base::OkStatus();
130     }
131   }
132   while (++key_ < stats::kNumKeys) {
133     cur_entry = &storage_->stats()[key_];
134     index_ = cur_entry->indexed_values.begin();
135     if (stats::kTypes[key_] == stats::kSingle ||
136         !cur_entry->indexed_values.empty()) {
137       break;
138     }
139   }
140   return base::OkStatus();
141 }
142 
Eof()143 bool StatsTable::Cursor::Eof() {
144   return key_ >= stats::kNumKeys;
145 }
146 
147 }  // namespace trace_processor
148 }  // namespace perfetto
149