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/window_operator_table.h"
     18 
     19 #include "src/trace_processor/sqlite_utils.h"
     20 
     21 namespace perfetto {
     22 namespace trace_processor {
     23 
     24 namespace {
     25 using namespace sqlite_utils;
     26 }  // namespace
     27 
     28 WindowOperatorTable::WindowOperatorTable(sqlite3*, const TraceStorage*) {}
     29 
     30 void WindowOperatorTable::RegisterTable(sqlite3* db,
     31                                         const TraceStorage* storage) {
     32   Table::Register<WindowOperatorTable>(db, storage, "window", true);
     33 }
     34 
     35 base::Optional<Table::Schema> WindowOperatorTable::Init(int,
     36                                                         const char* const*) {
     37   const bool kHidden = true;
     38   return Schema(
     39       {
     40           // These are the operator columns:
     41           Table::Column(Column::kRowId, "rowid", ColumnType::kLong, kHidden),
     42           Table::Column(Column::kQuantum, "quantum", ColumnType::kLong,
     43                         kHidden),
     44           Table::Column(Column::kWindowStart, "window_start", ColumnType::kLong,
     45                         kHidden),
     46           Table::Column(Column::kWindowDur, "window_dur", ColumnType::kLong,
     47                         kHidden),
     48           // These are the ouput columns:
     49           Table::Column(Column::kTs, "ts", ColumnType::kLong),
     50           Table::Column(Column::kDuration, "dur", ColumnType::kLong),
     51           Table::Column(Column::kQuantumTs, "quantum_ts", ColumnType::kLong),
     52       },
     53       {Column::kRowId});
     54 }
     55 
     56 std::unique_ptr<Table::Cursor> WindowOperatorTable::CreateCursor() {
     57   return std::unique_ptr<Table::Cursor>(new Cursor(this));
     58 }
     59 
     60 int WindowOperatorTable::BestIndex(const QueryConstraints& qc,
     61                                    BestIndexInfo* info) {
     62   // Remove ordering on timestamp if it is the only ordering as we are already
     63   // sorted on TS. This makes span joining significantly faster.
     64   if (qc.order_by().size() == 1 && qc.order_by()[0].iColumn == Column::kTs &&
     65       !qc.order_by()[0].desc) {
     66     info->order_by_consumed = true;
     67   }
     68   return SQLITE_OK;
     69 }
     70 
     71 int WindowOperatorTable::Update(int argc,
     72                                 sqlite3_value** argv,
     73                                 sqlite3_int64*) {
     74   // We only support updates to ts and dur. Disallow deletes (argc == 1) and
     75   // inserts (argv[0] == null).
     76   if (argc < 2 || sqlite3_value_type(argv[0]) == SQLITE_NULL)
     77     return SQLITE_READONLY;
     78 
     79   int64_t new_quantum = sqlite3_value_int64(argv[3]);
     80   int64_t new_start = sqlite3_value_int64(argv[4]);
     81   int64_t new_dur = sqlite3_value_int64(argv[5]);
     82   if (new_dur == 0) {
     83     auto* err = sqlite3_mprintf("Cannot set duration of window table to zero.");
     84     SetErrorMessage(err);
     85     return SQLITE_ERROR;
     86   }
     87 
     88   quantum_ = new_quantum;
     89   window_start_ = new_start;
     90   window_dur_ = new_dur;
     91 
     92   return SQLITE_OK;
     93 }
     94 
     95 WindowOperatorTable::Cursor::Cursor(WindowOperatorTable* table)
     96     : Table::Cursor(table), table_(table) {}
     97 
     98 int WindowOperatorTable::Cursor::Filter(const QueryConstraints& qc,
     99                                         sqlite3_value** argv) {
    100   *this = Cursor(table_);
    101   window_start_ = table_->window_start_;
    102   window_end_ = table_->window_start_ + table_->window_dur_;
    103   step_size_ = table_->quantum_ == 0 ? table_->window_dur_ : table_->quantum_;
    104 
    105   current_ts_ = window_start_;
    106 
    107   // Set return first if there is a equals constraint on the row id asking to
    108   // return the first row.
    109   bool return_first = qc.constraints().size() == 1 &&
    110                       qc.constraints()[0].iColumn == Column::kRowId &&
    111                       IsOpEq(qc.constraints()[0].op) &&
    112                       sqlite3_value_int(argv[0]) == 0;
    113   if (return_first) {
    114     filter_type_ = FilterType::kReturnFirst;
    115   } else {
    116     filter_type_ = FilterType::kReturnAll;
    117   }
    118   return SQLITE_OK;
    119 }
    120 
    121 int WindowOperatorTable::Cursor::Column(sqlite3_context* context, int N) {
    122   switch (N) {
    123     case Column::kQuantum: {
    124       sqlite3_result_int64(context,
    125                            static_cast<sqlite_int64>(table_->quantum_));
    126       break;
    127     }
    128     case Column::kWindowStart: {
    129       sqlite3_result_int64(context,
    130                            static_cast<sqlite_int64>(table_->window_start_));
    131       break;
    132     }
    133     case Column::kWindowDur: {
    134       sqlite3_result_int(context, static_cast<int>(table_->window_dur_));
    135       break;
    136     }
    137     case Column::kTs: {
    138       sqlite3_result_int64(context, static_cast<sqlite_int64>(current_ts_));
    139       break;
    140     }
    141     case Column::kDuration: {
    142       sqlite3_result_int64(context, static_cast<sqlite_int64>(step_size_));
    143       break;
    144     }
    145     case Column::kQuantumTs: {
    146       sqlite3_result_int64(context, static_cast<sqlite_int64>(quantum_ts_));
    147       break;
    148     }
    149     case Column::kRowId: {
    150       sqlite3_result_int64(context, static_cast<sqlite_int64>(row_id_));
    151       break;
    152     }
    153     default: {
    154       PERFETTO_FATAL("Unknown column %d", N);
    155       break;
    156     }
    157   }
    158   return SQLITE_OK;
    159 }
    160 
    161 int WindowOperatorTable::Cursor::Next() {
    162   switch (filter_type_) {
    163     case FilterType::kReturnFirst:
    164       current_ts_ = window_end_;
    165       break;
    166     case FilterType::kReturnAll:
    167       current_ts_ += step_size_;
    168       quantum_ts_++;
    169       break;
    170   }
    171   row_id_++;
    172   return SQLITE_OK;
    173 }
    174 
    175 int WindowOperatorTable::Cursor::Eof() {
    176   return current_ts_ >= window_end_;
    177 }
    178 
    179 }  // namespace trace_processor
    180 }  // namespace perfetto
    181