| /* | |
| * 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/sqlite/module_state_manager.h" | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <memory> | |
| #include <string> | |
| #include <utility> | |
| #include <vector> | |
| #include "perfetto/base/logging.h" | |
| namespace perfetto::trace_processor::sqlite { | |
| void ModuleStateManagerBase::OnCommit() { | |
| std::vector<std::string> to_erase; | |
| for (auto it = state_by_name_.GetIterator(); it; ++it) { | |
| if (auto& state = it.value(); state->active_state) { | |
| state->committed_state = state->active_state; | |
| state->savepoint_states.clear(); | |
| } else { | |
| to_erase.push_back(it.key()); | |
| } | |
| } | |
| for (const auto& name : to_erase) { | |
| state_by_name_.Erase(name); | |
| } | |
| } | |
| void ModuleStateManagerBase::OnRollback() { | |
| std::vector<std::string> to_erase; | |
| for (auto it = state_by_name_.GetIterator(); it; ++it) { | |
| if (auto& state = it.value(); state->committed_state) { | |
| state->active_state = state->committed_state; | |
| state->savepoint_states.clear(); | |
| } else { | |
| to_erase.push_back(it.key()); | |
| } | |
| } | |
| for (const auto& name : to_erase) { | |
| state_by_name_.Erase(name); | |
| } | |
| } | |
| ModuleStateManagerBase::PerVtabState* ModuleStateManagerBase::OnCreate( | |
| int, | |
| const char* const* argv, | |
| std::unique_ptr<void, void (*)(void*)> state) { | |
| auto [it, inserted] = state_by_name_.Insert(argv[2], nullptr); | |
| if (inserted) { | |
| *it = std::make_unique<PerVtabState>(); | |
| auto* s_ptr = it->get(); | |
| s_ptr->manager = this; | |
| s_ptr->name = argv[2]; | |
| } | |
| auto* s_ptr = it->get(); | |
| PERFETTO_CHECK(!s_ptr->active_state); | |
| s_ptr->active_state = std::move(state); | |
| return s_ptr; | |
| } | |
| ModuleStateManagerBase::PerVtabState* ModuleStateManagerBase::OnConnect( | |
| int, | |
| const char* const* argv) { | |
| auto* ptr = state_by_name_.Find(argv[2]); | |
| PERFETTO_CHECK(ptr); | |
| return ptr->get(); | |
| } | |
| void ModuleStateManagerBase::OnDestroy(PerVtabState* state) { | |
| auto* ptr = state->manager->state_by_name_.Find(state->name); | |
| PERFETTO_CHECK(ptr); | |
| PERFETTO_CHECK(ptr->get() == state); | |
| state->active_state.reset(); | |
| } | |
| void ModuleStateManagerBase::OnSavepoint(PerVtabState* s, int idx) { | |
| auto new_size = static_cast<uint32_t>(idx + 1); | |
| s->savepoint_states.resize(new_size, s->savepoint_states.empty() | |
| ? s->committed_state | |
| : s->savepoint_states.back()); | |
| s->savepoint_states[new_size - 1] = s->active_state; | |
| } | |
| void ModuleStateManagerBase::OnRelease(PerVtabState* s, int idx) { | |
| auto release_idx = static_cast<uint32_t>(idx); | |
| PERFETTO_CHECK(release_idx <= s->savepoint_states.size()); | |
| s->savepoint_states.resize(release_idx); | |
| } | |
| void ModuleStateManagerBase::OnRollbackTo(PerVtabState* s, int idx) { | |
| auto new_size = static_cast<uint32_t>(idx + 1); | |
| PERFETTO_CHECK(new_size <= s->savepoint_states.size()); | |
| s->active_state = | |
| new_size == 0 ? s->committed_state : s->savepoint_states[new_size - 1]; | |
| s->savepoint_states.resize(new_size); | |
| } | |
| void* ModuleStateManagerBase::GetState(PerVtabState* s) { | |
| return s->active_state.get(); | |
| } | |
| void* ModuleStateManagerBase::GetStateByName(const std::string& name) { | |
| auto* ptr = state_by_name_.Find(name); | |
| if (!ptr) { | |
| return nullptr; | |
| } | |
| return GetState(ptr->get()); | |
| } | |
| } // namespace perfetto::trace_processor::sqlite |