| /* | 
 |  * Copyright (C) 2019 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #include "src/trace_processor/args_tracker.h" | 
 |  | 
 | #include <algorithm> | 
 |  | 
 | namespace perfetto { | 
 | namespace trace_processor { | 
 |  | 
 | ArgsTracker::ArgsTracker(TraceProcessorContext* context) : context_(context) {} | 
 |  | 
 | ArgsTracker::~ArgsTracker() { | 
 |   Flush(); | 
 | } | 
 |  | 
 | void ArgsTracker::AddArg(Column* arg_set_id, | 
 |                          uint32_t row, | 
 |                          StringId flat_key, | 
 |                          StringId key, | 
 |                          Variadic value, | 
 |                          UpdatePolicy update_policy) { | 
 |   args_.emplace_back(); | 
 |  | 
 |   auto* rid_arg = &args_.back(); | 
 |   rid_arg->column = arg_set_id; | 
 |   rid_arg->row = row; | 
 |   rid_arg->flat_key = flat_key; | 
 |   rid_arg->key = key; | 
 |   rid_arg->value = value; | 
 |   rid_arg->update_policy = update_policy; | 
 | } | 
 |  | 
 | void ArgsTracker::Flush() { | 
 |   using Arg = GlobalArgsTracker::Arg; | 
 |  | 
 |   if (args_.empty()) | 
 |     return; | 
 |  | 
 |   // We sort here because a single packet may add multiple args with different | 
 |   // rowids. | 
 |   auto comparator = [](const Arg& f, const Arg& s) { | 
 |     // We only care that all args for a specific arg set appear in a contiguous | 
 |     // block and that args within one arg set are sorted by key, but not about | 
 |     // the relative order of one block to another. The simplest way to achieve | 
 |     // that is to sort by table column pointer & row, which identify the arg | 
 |     // set, and then by key. | 
 |     if (f.column == s.column && f.row == s.row) | 
 |       return f.key < s.key; | 
 |     if (f.column == s.column) | 
 |       return f.row < s.row; | 
 |     return f.column < s.column; | 
 |   }; | 
 |   std::stable_sort(args_.begin(), args_.end(), comparator); | 
 |  | 
 |   for (uint32_t i = 0; i < args_.size();) { | 
 |     const auto& arg = args_[i]; | 
 |     Column* column = arg.column; | 
 |     auto row = arg.row; | 
 |  | 
 |     uint32_t next_rid_idx = i + 1; | 
 |     while (next_rid_idx < args_.size() && | 
 |            column == args_[next_rid_idx].column && | 
 |            row == args_[next_rid_idx].row) { | 
 |       next_rid_idx++; | 
 |     } | 
 |  | 
 |     ArgSetId set_id = | 
 |         context_->global_args_tracker->AddArgSet(args_, i, next_rid_idx); | 
 |     column->Set(row, SqlValue::Long(set_id)); | 
 |  | 
 |     i = next_rid_idx; | 
 |   } | 
 |   args_.clear(); | 
 | } | 
 |  | 
 | ArgsTracker::BoundInserter::BoundInserter(ArgsTracker* args_tracker, | 
 |                                           Column* arg_set_id_column, | 
 |                                           uint32_t row) | 
 |     : args_tracker_(args_tracker), | 
 |       arg_set_id_column_(arg_set_id_column), | 
 |       row_(row) {} | 
 |  | 
 | ArgsTracker::BoundInserter::~BoundInserter() {} | 
 |  | 
 | }  // namespace trace_processor | 
 | }  // namespace perfetto |