Home | History | Annotate | Download | only in trace_processor
      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/thread_table.h"
     18 
     19 #include "perfetto/base/logging.h"
     20 #include "src/trace_processor/query_constraints.h"
     21 #include "src/trace_processor/sqlite_utils.h"
     22 
     23 namespace perfetto {
     24 namespace trace_processor {
     25 
     26 namespace {
     27 
     28 using namespace sqlite_utils;
     29 
     30 }  // namespace
     31 
     32 ThreadTable::ThreadTable(sqlite3*, const TraceStorage* storage)
     33     : storage_(storage) {}
     34 
     35 void ThreadTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
     36   Table::Register<ThreadTable>(db, storage, "thread");
     37 }
     38 
     39 base::Optional<Table::Schema> ThreadTable::Init(int, const char* const*) {
     40   return Schema(
     41       {
     42           Table::Column(Column::kUtid, "utid", ColumnType::kInt),
     43           Table::Column(Column::kUpid, "upid", ColumnType::kInt),
     44           Table::Column(Column::kName, "name", ColumnType::kString),
     45           Table::Column(Column::kTid, "tid", ColumnType::kInt),
     46           Table::Column(Column::kStartTs, "start_ts", ColumnType::kLong),
     47       },
     48       {Column::kUtid});
     49 }
     50 
     51 std::unique_ptr<Table::Cursor> ThreadTable::CreateCursor() {
     52   return std::unique_ptr<Table::Cursor>(new Cursor(this));
     53 }
     54 
     55 int ThreadTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
     56   info->estimated_cost = static_cast<uint32_t>(storage_->thread_count());
     57 
     58   // If the query has a constraint on the |utid| field, return a reduced cost
     59   // because we can do that filter efficiently.
     60   const auto& constraints = qc.constraints();
     61   for (const auto& cs : qc.constraints()) {
     62     if (cs.iColumn == Column::kUtid) {
     63       info->estimated_cost = IsOpEq(constraints.front().op) ? 1 : 10;
     64     }
     65   }
     66   return SQLITE_OK;
     67 }
     68 
     69 ThreadTable::Cursor::Cursor(ThreadTable* table)
     70     : Table::Cursor(table), storage_(table->storage_), table_(table) {}
     71 
     72 int ThreadTable::Cursor::Filter(const QueryConstraints& qc,
     73                                 sqlite3_value** argv) {
     74   *this = Cursor(table_);
     75 
     76   min = 0;
     77   max = static_cast<uint32_t>(storage_->thread_count()) - 1;
     78   desc = false;
     79   current = min;
     80   for (size_t j = 0; j < qc.constraints().size(); j++) {
     81     const auto& cs = qc.constraints()[j];
     82     if (cs.iColumn == Column::kUtid) {
     83       UniqueTid constraint_utid =
     84           static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
     85       // Filter the range of utids that we are interested in, based on the
     86       // constraints in the query. Everything between min and max (inclusive)
     87       // will be returned.
     88       if (IsOpEq(cs.op)) {
     89         min = constraint_utid;
     90         max = constraint_utid;
     91       } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
     92         min = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
     93       } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
     94         max = IsOpLt(cs.op) ? constraint_utid - 1 : constraint_utid;
     95       }
     96     }
     97   }
     98   for (const auto& ob : qc.order_by()) {
     99     if (ob.iColumn == Column::kUtid) {
    100       desc = ob.desc;
    101       current = desc ? max : min;
    102     }
    103   }
    104   return SQLITE_OK;
    105 }
    106 
    107 int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
    108   const auto& thread = storage_->GetThread(current);
    109   switch (N) {
    110     case Column::kUtid: {
    111       sqlite3_result_int64(context, current);
    112       break;
    113     }
    114     case Column::kUpid: {
    115       if (thread.upid.has_value()) {
    116         sqlite3_result_int64(context, thread.upid.value());
    117       } else {
    118         sqlite3_result_null(context);
    119       }
    120       break;
    121     }
    122     case Column::kName: {
    123       const auto& name = storage_->GetString(thread.name_id);
    124       sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
    125       break;
    126     }
    127     case Column::kTid: {
    128       sqlite3_result_int64(context, thread.tid);
    129       break;
    130     }
    131     case Column::kStartTs: {
    132       if (thread.start_ns != 0) {
    133         sqlite3_result_int64(context, thread.start_ns);
    134       } else {
    135         sqlite3_result_null(context);
    136       }
    137       break;
    138     }
    139     default: {
    140       PERFETTO_FATAL("Unknown column %d", N);
    141       break;
    142     }
    143   }
    144   return SQLITE_OK;
    145 }
    146 
    147 int ThreadTable::Cursor::Next() {
    148   if (desc) {
    149     --current;
    150   } else {
    151     ++current;
    152   }
    153   return SQLITE_OK;
    154 }
    155 
    156 int ThreadTable::Cursor::Eof() {
    157   return desc ? current < min : current > max;
    158 }
    159 }  // namespace trace_processor
    160 }  // namespace perfetto
    161