[Impeller] Delete the archivist framework. (flutter/engine#50474)

It is unused and can be brought back from Git if needed. This unnecessarily adds to binary size estimates on standalone Impeller investigations.
This commit is contained in:
Chinmay Garde 2024-02-08 14:49:00 -08:00 committed by GitHub
parent dcf2e52abf
commit 437c939632
25 changed files with 0 additions and 1923 deletions

View File

@ -132,7 +132,6 @@
../../../flutter/impeller/aiks/canvas_unittests.cc
../../../flutter/impeller/aiks/testing
../../../flutter/impeller/aiks/trace_serializer_unittests.cc
../../../flutter/impeller/archivist/archivist_unittests.cc
../../../flutter/impeller/base/README.md
../../../flutter/impeller/base/base_unittests.cc
../../../flutter/impeller/compiler/README.md

View File

@ -4961,24 +4961,6 @@ ORIGIN: ../../../flutter/impeller/aiks/picture_recorder.cc + ../../../flutter/LI
ORIGIN: ../../../flutter/impeller/aiks/picture_recorder.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/aiks/trace_serializer.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/aiks/trace_serializer.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archivable.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archivable.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_class_registration.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_class_registration.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_database.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_database.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_location.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_location.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_statement.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_statement.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_transaction.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_transaction.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_vector.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archive_vector.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archivist_fixture.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/archivist/archivist_fixture.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/allocation.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/allocation.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/backend_cast.h + ../../../flutter/LICENSE
@ -7818,24 +7800,6 @@ FILE: ../../../flutter/impeller/aiks/picture_recorder.cc
FILE: ../../../flutter/impeller/aiks/picture_recorder.h
FILE: ../../../flutter/impeller/aiks/trace_serializer.cc
FILE: ../../../flutter/impeller/aiks/trace_serializer.h
FILE: ../../../flutter/impeller/archivist/archivable.cc
FILE: ../../../flutter/impeller/archivist/archivable.h
FILE: ../../../flutter/impeller/archivist/archive.cc
FILE: ../../../flutter/impeller/archivist/archive.h
FILE: ../../../flutter/impeller/archivist/archive_class_registration.cc
FILE: ../../../flutter/impeller/archivist/archive_class_registration.h
FILE: ../../../flutter/impeller/archivist/archive_database.cc
FILE: ../../../flutter/impeller/archivist/archive_database.h
FILE: ../../../flutter/impeller/archivist/archive_location.cc
FILE: ../../../flutter/impeller/archivist/archive_location.h
FILE: ../../../flutter/impeller/archivist/archive_statement.cc
FILE: ../../../flutter/impeller/archivist/archive_statement.h
FILE: ../../../flutter/impeller/archivist/archive_transaction.cc
FILE: ../../../flutter/impeller/archivist/archive_transaction.h
FILE: ../../../flutter/impeller/archivist/archive_vector.cc
FILE: ../../../flutter/impeller/archivist/archive_vector.h
FILE: ../../../flutter/impeller/archivist/archivist_fixture.cc
FILE: ../../../flutter/impeller/archivist/archivist_fixture.h
FILE: ../../../flutter/impeller/base/allocation.cc
FILE: ../../../flutter/impeller/base/allocation.h
FILE: ../../../flutter/impeller/base/backend_cast.h

View File

@ -56,7 +56,6 @@ config("impeller_public_config") {
group("impeller") {
public_deps = [
"archivist",
"base",
"geometry",
"tessellator",
@ -81,7 +80,6 @@ impeller_component("impeller_unittests") {
testonly = true
deps = [
"archivist:archivist_unittests",
"base:base_unittests",
"compiler:compiler_unittests",
"core:allocator_unittests",

View File

@ -60,12 +60,6 @@ states of completion:
for a specific client rendering API. The interfaces in these targets are
meant to be private for non-WSI user targets. No Impeller sub-frameworks
may depend on these targets.
* **`//impeller/archivist`**: Allows persisting objects to disk as performantly
as possible (usually on a background thread). The framework is meant to be
used for storing frame meta-data and related profiling/instrumentation
information. Collection of information should succeed despite process crashes
and retrieval of traces must not use inordinate amounts of time or memory
(which usually leads to crashes).
* **`//impeller/geometry`**: All (or, most of) the math! This C++ mathematics
library is used extensively by Impeller and its clients. The reasonably
interesting bit about this library is that all types can be used

View File

@ -1,51 +0,0 @@
# Copyright 2013 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../tools/impeller.gni")
impeller_component("archivist") {
public = [
"archivable.h",
"archive.h",
"archive_location.h",
]
sources = [
"archivable.cc",
"archivable.h",
"archive.cc",
"archive.h",
"archive_class_registration.cc",
"archive_class_registration.h",
"archive_database.cc",
"archive_database.h",
"archive_location.cc",
"archive_statement.cc",
"archive_statement.h",
"archive_transaction.cc",
"archive_transaction.h",
"archive_vector.cc",
"archive_vector.h",
]
public_deps = [ "../base" ]
deps = [
"//flutter/fml",
"//flutter/third_party/sqlite",
]
}
impeller_component("archivist_unittests") {
testonly = true
sources = [
"archivist_fixture.cc",
"archivist_fixture.h",
"archivist_unittests.cc",
]
deps = [
":archivist",
"//flutter/testing",
]
}

View File

@ -1,11 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archivable.h"
namespace impeller {
//
} // namespace impeller

View File

@ -1,41 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVABLE_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVABLE_H_
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace impeller {
struct ArchiveDef {
const std::string table_name;
const std::vector<std::string> members;
};
class ArchiveLocation;
using PrimaryKey = std::optional<int64_t>;
//------------------------------------------------------------------------------
/// @brief Instances of `Archivable`s can be read from and written to a
/// persistent archive.
///
class Archivable {
public:
virtual ~Archivable() = default;
virtual PrimaryKey GetPrimaryKey() const = 0;
virtual bool Write(ArchiveLocation& item) const = 0;
virtual bool Read(ArchiveLocation& item) = 0;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVABLE_H_

View File

@ -1,172 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archive.h"
#include "flutter/fml/logging.h"
#include "impeller/archivist/archive_class_registration.h"
#include "impeller/archivist/archive_database.h"
#include "impeller/archivist/archive_location.h"
namespace impeller {
Archive::Archive(const std::string& path)
: database_(std::make_unique<ArchiveDatabase>(path)) {}
Archive::~Archive() {
FML_DCHECK(transaction_count_ == 0)
<< "There must be no pending transactions";
}
bool Archive::IsValid() const {
return database_->IsValid();
}
std::optional<int64_t /* row id */> Archive::ArchiveInstance(
const ArchiveDef& definition,
const Archivable& archivable) {
if (!IsValid()) {
return std::nullopt;
}
auto transaction = database_->CreateTransaction(transaction_count_);
const auto* registration =
database_->GetRegistrationForDefinition(definition);
if (registration == nullptr) {
return std::nullopt;
}
auto statement = registration->CreateInsertStatement();
if (!statement.IsValid() || !statement.Reset()) {
/*
* Must be able to reset the statement for a new write
*/
return std::nullopt;
}
auto primary_key = archivable.GetPrimaryKey();
/*
* The lifecycle of the archive item is tied to this scope and there is no
* way for the user to create an instance of an archive item. So its safe
* for its members to be references. It does not manage the lifetimes of
* anything.
*/
ArchiveLocation item(*this, statement, *registration, primary_key);
/*
* If the item provides its own primary key, we need to bind it now.
* Otherwise, one will be automatically assigned to it.
*/
if (primary_key.has_value() &&
!statement.WriteValue(ArchiveClassRegistration::kPrimaryKeyIndex,
primary_key.value())) {
return std::nullopt;
}
if (!archivable.Write(item)) {
return std::nullopt;
}
if (statement.Execute() != ArchiveStatement::Result::kDone) {
return std::nullopt;
}
int64_t lastInsert = database_->GetLastInsertRowID();
if (primary_key.has_value() &&
lastInsert != static_cast<int64_t>(primary_key.value())) {
return std::nullopt;
}
/*
* If any of the nested calls fail, we would have already checked for the
* failure and returned.
*/
transaction.MarkWritesAsReadyForCommit();
return lastInsert;
}
bool Archive::UnarchiveInstance(const ArchiveDef& definition,
PrimaryKey name,
Archivable& archivable) {
UnarchiveStep stepper = [&archivable](ArchiveLocation& item) {
archivable.Read(item);
return false /* no-more after single read */;
};
return UnarchiveInstances(definition, stepper, name) == 1;
}
size_t Archive::UnarchiveInstances(const ArchiveDef& definition,
const Archive::UnarchiveStep& stepper,
PrimaryKey primary_key) {
if (!IsValid()) {
return 0;
}
const auto* registration =
database_->GetRegistrationForDefinition(definition);
if (registration == nullptr) {
return 0;
}
const bool isQueryingSingle = primary_key.has_value();
auto statement = registration->CreateQueryStatement(isQueryingSingle);
if (!statement.IsValid() || !statement.Reset()) {
return 0;
}
if (isQueryingSingle) {
/*
* If a single statement is being queried for, bind the primary key as a
* statement argument.
*/
if (!statement.WriteValue(ArchiveClassRegistration::kPrimaryKeyIndex,
primary_key.value())) {
return 0;
}
}
if (statement.GetColumnCount() !=
registration->GetMemberCount() + 1 /* primary key */) {
return 0;
}
/*
* Acquire a transaction but never mark it successful since we will never
* be committing any writes to the database during unarchiving.
*/
auto transaction = database_->CreateTransaction(transaction_count_);
size_t itemsRead = 0;
while (statement.Execute() == ArchiveStatement::Result::kRow) {
itemsRead++;
/*
* Prepare a fresh archive item for the given statement
*/
ArchiveLocation item(*this, statement, *registration, primary_key);
if (!stepper(item)) {
break;
}
if (isQueryingSingle) {
break;
}
}
return itemsRead;
}
} // namespace impeller

View File

@ -1,77 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_H_
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include "impeller/archivist/archivable.h"
namespace impeller {
class ArchiveLocation;
class ArchiveDatabase;
class Archive {
public:
explicit Archive(const std::string& path);
~Archive();
bool IsValid() const;
template <class T,
class = std::enable_if_t<std::is_base_of<Archivable, T>::value>>
[[nodiscard]] bool Write(const T& archivable) {
const ArchiveDef& def = T::kArchiveDefinition;
return ArchiveInstance(def, archivable).has_value();
}
template <class T,
class = std::enable_if_t<std::is_base_of<Archivable, T>::value>>
[[nodiscard]] bool Read(PrimaryKey name, T& archivable) {
const ArchiveDef& def = T::kArchiveDefinition;
return UnarchiveInstance(def, name, archivable);
}
using UnarchiveStep = std::function<bool(ArchiveLocation&)>;
template <class T,
class = std::enable_if_t<std::is_base_of<Archivable, T>::value>>
[[nodiscard]] size_t Read(const UnarchiveStep& stepper) {
const ArchiveDef& def = T::kArchiveDefinition;
return UnarchiveInstances(def, stepper);
}
private:
std::unique_ptr<ArchiveDatabase> database_;
int64_t transaction_count_ = 0;
friend class ArchiveLocation;
std::optional<int64_t /* row id */> ArchiveInstance(
const ArchiveDef& definition,
const Archivable& archivable);
bool UnarchiveInstance(const ArchiveDef& definition,
PrimaryKey name,
Archivable& archivable);
size_t UnarchiveInstances(const ArchiveDef& definition,
const UnarchiveStep& stepper,
PrimaryKey primary_key = std::nullopt);
Archive(const Archive&) = delete;
Archive& operator=(const Archive&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_H_

View File

@ -1,124 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archive_class_registration.h"
#include <sstream>
#include "impeller/archivist/archive_database.h"
#include "impeller/archivist/archive_statement.h"
#include "impeller/base/validation.h"
namespace impeller {
static constexpr const char* kArchivePrimaryKeyColumnName = "primary_key";
ArchiveClassRegistration::ArchiveClassRegistration(ArchiveDatabase& database,
ArchiveDef definition)
: database_(database), definition_(std::move(definition)) {
for (size_t i = 0; i < definition_.members.size(); i++) {
// The first index entry is the primary key. So add one to the index.
column_map_[definition_.members[i]] = i + 1;
}
is_valid_ = CreateTable();
}
const std::string& ArchiveClassRegistration::GetClassName() const {
return definition_.table_name;
}
size_t ArchiveClassRegistration::GetMemberCount() const {
return column_map_.size();
}
bool ArchiveClassRegistration::IsValid() const {
return is_valid_;
}
std::optional<size_t> ArchiveClassRegistration::FindColumnIndex(
const std::string& member) const {
auto found = column_map_.find(member);
if (found == column_map_.end()) {
VALIDATION_LOG << "No member named '" << member << "' in class '"
<< definition_.table_name
<< "'. Did you forget to register it?";
return std::nullopt;
}
return found->second;
}
bool ArchiveClassRegistration::CreateTable() {
if (definition_.table_name.empty() || definition_.members.empty()) {
return false;
}
std::stringstream stream;
/*
* Table names cannot participate in parameter substitution, so we prepare
* a statement and check its validity before running.
*/
stream << "CREATE TABLE IF NOT EXISTS " << definition_.table_name << " ("
<< kArchivePrimaryKeyColumnName << " INTEGER PRIMARY KEY, ";
for (size_t i = 0, columns = definition_.members.size(); i < columns; i++) {
stream << definition_.members[i];
if (i != columns - 1) {
stream << ", ";
}
}
stream << ");";
auto statement = database_.CreateStatement(stream.str());
if (!statement.IsValid()) {
return false;
}
if (!statement.Reset()) {
return false;
}
return statement.Execute() == ArchiveStatement::Result::kDone;
}
ArchiveStatement ArchiveClassRegistration::CreateQueryStatement(
bool single) const {
std::stringstream stream;
stream << "SELECT " << kArchivePrimaryKeyColumnName << ", ";
for (size_t i = 0, columns = definition_.members.size(); i < columns; i++) {
stream << definition_.members[i];
if (i != columns - 1) {
stream << ",";
}
}
stream << " FROM " << definition_.table_name;
if (single) {
stream << " WHERE " << kArchivePrimaryKeyColumnName << " = ?";
} else {
stream << " ORDER BY " << kArchivePrimaryKeyColumnName << " ASC";
}
stream << ";";
return database_.CreateStatement(stream.str());
}
ArchiveStatement ArchiveClassRegistration::CreateInsertStatement() const {
std::stringstream stream;
stream << "INSERT OR REPLACE INTO " << definition_.table_name
<< " VALUES ( ?, ";
for (size_t i = 0, columns = definition_.members.size(); i < columns; i++) {
stream << "?";
if (i != columns - 1) {
stream << ", ";
}
}
stream << ");";
return database_.CreateStatement(stream.str());
}
} // namespace impeller

View File

@ -1,54 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_CLASS_REGISTRATION_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_CLASS_REGISTRATION_H_
#include <map>
#include <optional>
#include "flutter/fml/macros.h"
#include "impeller/archivist/archive.h"
#include "impeller/archivist/archive_statement.h"
namespace impeller {
class ArchiveClassRegistration {
public:
static constexpr size_t kPrimaryKeyIndex = 0u;
bool IsValid() const;
std::optional<size_t> FindColumnIndex(const std::string& member) const;
const std::string& GetClassName() const;
size_t GetMemberCount() const;
ArchiveStatement CreateInsertStatement() const;
ArchiveStatement CreateQueryStatement(bool single) const;
private:
using MemberColumnMap = std::map<std::string, size_t>;
friend class ArchiveDatabase;
ArchiveClassRegistration(ArchiveDatabase& database, ArchiveDef definition);
bool CreateTable();
ArchiveDatabase& database_;
const ArchiveDef definition_;
MemberColumnMap column_map_;
bool is_valid_ = false;
ArchiveClassRegistration(const ArchiveClassRegistration&) = delete;
ArchiveClassRegistration& operator=(const ArchiveClassRegistration&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_CLASS_REGISTRATION_H_

View File

@ -1,143 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archive_database.h"
#include "third_party/sqlite/sqlite3.h"
#include <sstream>
#include <string>
#include "impeller/archivist/archive.h"
#include "impeller/archivist/archive_class_registration.h"
#include "impeller/archivist/archive_statement.h"
#include "impeller/base/validation.h"
namespace impeller {
struct ArchiveDatabase::Handle {
explicit Handle(const std::string& filename) {
if (::sqlite3_initialize() != SQLITE_OK) {
VALIDATION_LOG << "Could not initialize sqlite.";
return;
}
sqlite3* db = nullptr;
auto res = ::sqlite3_open(filename.c_str(), &db);
if (res != SQLITE_OK || db == nullptr) {
return;
}
handle_ = db;
}
~Handle() {
if (handle_ == nullptr) {
return;
}
::sqlite3_close(handle_);
}
::sqlite3* Get() const { return handle_; }
bool IsValid() const { return handle_ != nullptr; }
private:
::sqlite3* handle_ = nullptr;
Handle(const Handle&) = delete;
Handle& operator=(const Handle&) = delete;
};
ArchiveDatabase::ArchiveDatabase(const std::string& filename)
: handle_(std::make_unique<Handle>(filename)) {
if (!handle_->IsValid()) {
handle_.reset();
return;
}
begin_transaction_stmt_ = std::unique_ptr<ArchiveStatement>(
new ArchiveStatement(handle_->Get(), "BEGIN TRANSACTION;"));
if (!begin_transaction_stmt_->IsValid()) {
return;
}
end_transaction_stmt_ = std::unique_ptr<ArchiveStatement>(
new ArchiveStatement(handle_->Get(), "END TRANSACTION;"));
if (!end_transaction_stmt_->IsValid()) {
return;
}
rollback_transaction_stmt_ = std::unique_ptr<ArchiveStatement>(
new ArchiveStatement(handle_->Get(), "ROLLBACK TRANSACTION;"));
if (!rollback_transaction_stmt_->IsValid()) {
return;
}
}
ArchiveDatabase::~ArchiveDatabase() = default;
bool ArchiveDatabase::IsValid() const {
return handle_ != nullptr;
}
int64_t ArchiveDatabase::GetLastInsertRowID() {
if (!IsValid()) {
return 0u;
}
return ::sqlite3_last_insert_rowid(handle_->Get());
}
static inline const ArchiveClassRegistration* RegistrationIfReady(
const ArchiveClassRegistration* registration) {
if (registration == nullptr) {
return nullptr;
}
return registration->IsValid() ? registration : nullptr;
}
const ArchiveClassRegistration* ArchiveDatabase::GetRegistrationForDefinition(
const ArchiveDef& definition) {
auto found = registrations_.find(definition.table_name);
if (found != registrations_.end()) {
/*
* This class has already been registered.
*/
return RegistrationIfReady(found->second.get());
}
/*
* Initialize a new class registration for the given class definition.
*/
auto registration = std::unique_ptr<ArchiveClassRegistration>(
new ArchiveClassRegistration(*this, definition));
auto res =
registrations_.emplace(definition.table_name, std::move(registration));
/*
* If the new class registration is ready, return it to the caller.
*/
return res.second ? RegistrationIfReady((*(res.first)).second.get())
: nullptr;
}
ArchiveStatement ArchiveDatabase::CreateStatement(
const std::string& statementString) const {
return ArchiveStatement{handle_ ? handle_->Get() : nullptr, statementString};
}
ArchiveTransaction ArchiveDatabase::CreateTransaction(
int64_t& transactionCount) {
return ArchiveTransaction{transactionCount, //
*begin_transaction_stmt_, //
*end_transaction_stmt_, //
*rollback_transaction_stmt_};
}
} // namespace impeller

View File

@ -1,58 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_DATABASE_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_DATABASE_H_
#include <map>
#include <memory>
#include <string>
#include "impeller/archivist/archive_transaction.h"
namespace impeller {
class ArchiveStatement;
class ArchiveClassRegistration;
struct ArchiveDef;
//------------------------------------------------------------------------------
/// @brief A handle to the underlying database connection for an archive.
///
class ArchiveDatabase {
public:
explicit ArchiveDatabase(const std::string& filename);
~ArchiveDatabase();
bool IsValid() const;
int64_t GetLastInsertRowID();
const ArchiveClassRegistration* GetRegistrationForDefinition(
const ArchiveDef& definition);
ArchiveTransaction CreateTransaction(int64_t& transactionCount);
private:
struct Handle;
std::unique_ptr<Handle> handle_;
std::map<std::string, std::unique_ptr<ArchiveClassRegistration>>
registrations_;
std::unique_ptr<ArchiveStatement> begin_transaction_stmt_;
std::unique_ptr<ArchiveStatement> end_transaction_stmt_;
std::unique_ptr<ArchiveStatement> rollback_transaction_stmt_;
friend class ArchiveClassRegistration;
ArchiveStatement CreateStatement(const std::string& statementString) const;
ArchiveDatabase(const ArchiveDatabase&) = delete;
ArchiveDatabase& operator=(const ArchiveDatabase&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_DATABASE_H_

View File

@ -1,143 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archive_location.h"
#include "impeller/archivist/archive_class_registration.h"
#include "impeller/archivist/archive_vector.h"
namespace impeller {
ArchiveLocation::ArchiveLocation(Archive& context,
ArchiveStatement& statement,
const ArchiveClassRegistration& registration,
PrimaryKey name)
: context_(context),
statement_(statement),
registration_(registration),
primary_key_(name) {}
PrimaryKey ArchiveLocation::GetPrimaryKey() const {
return primary_key_;
}
bool ArchiveLocation::Write(const std::string& member,
const std::string& item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.WriteValue(index.value(), item) : false;
}
bool ArchiveLocation::WriteIntegral(const std::string& member, int64_t item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.WriteValue(index.value(), item) : false;
}
bool ArchiveLocation::Write(const std::string& member, double item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.WriteValue(index.value(), item) : false;
}
bool ArchiveLocation::Write(const std::string& member, const Allocation& item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.WriteValue(index.value(), item) : false;
}
bool ArchiveLocation::Write(const std::string& member,
const ArchiveDef& otherDef,
const Archivable& other) {
auto index = registration_.FindColumnIndex(member);
if (!index.has_value()) {
return false;
}
/*
* We need to fully archive the other instance first because it could
* have a name that is auto assigned. In that case, we cannot ask it before
* archival (via `other.archiveName()`).
*/
auto row_id = context_.ArchiveInstance(otherDef, other);
if (!row_id.has_value()) {
return false;
}
/*
* Bind the name of the serializable
*/
if (!statement_.WriteValue(index.value(), row_id.value())) {
return false;
}
return true;
}
std::optional<int64_t> ArchiveLocation::WriteVectorKeys(
std::vector<int64_t>&& members) {
ArchiveVector vector(std::move(members));
return context_.ArchiveInstance(ArchiveVector::kArchiveDefinition, vector);
}
bool ArchiveLocation::ReadVectorKeys(PrimaryKey name,
std::vector<int64_t>& members) {
ArchiveVector vector;
if (!context_.UnarchiveInstance(ArchiveVector::kArchiveDefinition, name,
vector)) {
return false;
}
const auto& keys = vector.GetKeys();
std::move(keys.begin(), keys.end(), std::back_inserter(members));
return true;
}
bool ArchiveLocation::Read(const std::string& member, std::string& item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.ReadValue(index.value(), item) : false;
}
bool ArchiveLocation::ReadIntegral(const std::string& member, int64_t& item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.ReadValue(index.value(), item) : false;
}
bool ArchiveLocation::Read(const std::string& member, double& item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.ReadValue(index.value(), item) : false;
}
bool ArchiveLocation::Read(const std::string& member, Allocation& item) {
auto index = registration_.FindColumnIndex(member);
return index.has_value() ? statement_.ReadValue(index.value(), item) : false;
}
bool ArchiveLocation::Read(const std::string& member,
const ArchiveDef& otherDef,
Archivable& other) {
auto index = registration_.FindColumnIndex(member);
/*
* Make sure a member is present at that column
*/
if (!index.has_value()) {
return false;
}
/*
* Try to find the foreign key in the current items row
*/
int64_t foreignKey = 0;
if (!statement_.ReadValue(index.value(), foreignKey)) {
return false;
}
/*
* Find the other item and unarchive by this foreign key
*/
if (!context_.UnarchiveInstance(otherDef, foreignKey, other)) {
return false;
}
return true;
}
} // namespace impeller

View File

@ -1,176 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_LOCATION_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_LOCATION_H_
#include <optional>
#include <type_traits>
#include "impeller/archivist/archivable.h"
#include "impeller/archivist/archive.h"
#include "impeller/base/allocation.h"
namespace impeller {
class Archive;
class ArchiveClassRegistration;
class ArchiveStatement;
class ArchiveLocation {
public:
PrimaryKey GetPrimaryKey() const;
template <class T, class = std::enable_if_t<std::is_integral<T>::value>>
bool Write(const std::string& member, T item) {
return WriteIntegral(member, static_cast<int64_t>(item));
}
bool Write(const std::string& member, double item);
bool Write(const std::string& member, const std::string& item);
bool Write(const std::string& member, const Allocation& allocation);
template <class T,
class = std::enable_if_t<std::is_base_of<Archivable, T>::value>>
bool WriteArchivable(const std::string& member, const T& other) {
const ArchiveDef& otherDef = T::ArchiveDefinition;
return Write(member, otherDef, other);
}
template <class T, class = std::enable_if_t<std::is_enum<T>::value>>
bool WriteEnum(const std::string& member, const T& item) {
return WriteIntegral(member, static_cast<int64_t>(item));
}
template <class T,
class = std::enable_if_t<std::is_base_of<Archivable, T>::value>>
bool Write(const std::string& member, const std::vector<T>& items) {
/*
* All items in the vector are individually encoded and their keys noted
*/
std::vector<int64_t> members;
members.reserve(items.size());
const ArchiveDef& itemDefinition = T::kArchiveDefinition;
for (const auto& item : items) {
auto row_id = context_.ArchiveInstance(itemDefinition, item);
if (!row_id.has_value()) {
return false;
}
members.emplace_back(row_id.value());
}
/*
* The keys are flattened into the vectors table. Write to that table
*/
auto vectorInsert = WriteVectorKeys(std::move(members));
if (!vectorInsert.has_value()) {
return false;
}
return WriteIntegral(member, vectorInsert.value());
}
template <class T, class = std::enable_if_t<std::is_integral<T>::value>>
bool Read(const std::string& member, T& item) {
int64_t decoded = 0;
auto result = ReadIntegral(member, decoded);
item = static_cast<T>(decoded);
return result;
}
bool Read(const std::string& member, double& item);
bool Read(const std::string& member, std::string& item);
bool Read(const std::string& member, Allocation& allocation);
template <class T,
class = std::enable_if_t<std::is_base_of<Archivable, T>::value>>
bool ReadArchivable(const std::string& member, T& other) {
const ArchiveDef& otherDef = T::ArchiveDefinition;
return decode(member, otherDef, other);
}
template <class T, class = std::enable_if_t<std::is_enum<T>::value>>
bool ReadEnum(const std::string& member, T& item) {
int64_t desugared = 0;
if (ReadIntegral(member, desugared)) {
item = static_cast<T>(desugared);
return true;
}
return false;
}
template <class T,
class = std::enable_if_t<std::is_base_of<Archivable, T>::value>>
bool Read(const std::string& member, std::vector<T>& items) {
/*
* From the member, find the foreign key of the vector
*/
int64_t vectorForeignKey = 0;
if (!ReadIntegral(member, vectorForeignKey)) {
return false;
}
/*
* Get vector keys
*/
std::vector<int64_t> keys;
if (!ReadVectorKeys(vectorForeignKey, keys)) {
return false;
}
const ArchiveDef& otherDef = T::kArchiveDefinition;
for (const auto& key : keys) {
items.emplace_back();
if (!context_.UnarchiveInstance(otherDef, key, items.back())) {
return false;
}
}
return true;
}
private:
Archive& context_;
ArchiveStatement& statement_;
const ArchiveClassRegistration& registration_;
PrimaryKey primary_key_;
friend class Archive;
ArchiveLocation(Archive& context,
ArchiveStatement& statement,
const ArchiveClassRegistration& registration,
PrimaryKey name);
bool WriteIntegral(const std::string& member, int64_t item);
bool ReadIntegral(const std::string& member, int64_t& item);
std::optional<int64_t> WriteVectorKeys(std::vector<int64_t>&& members);
bool ReadVectorKeys(PrimaryKey name, std::vector<int64_t>& members);
bool Write(const std::string& member,
const ArchiveDef& otherDef,
const Archivable& other);
bool Read(const std::string& member,
const ArchiveDef& otherDef,
Archivable& other);
ArchiveLocation(const ArchiveLocation&) = delete;
ArchiveLocation& operator=(const ArchiveLocation&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_LOCATION_H_

View File

@ -1,231 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archive_statement.h"
#include <string>
#include "flutter/fml/logging.h"
#include "third_party/sqlite/sqlite3.h"
namespace impeller {
struct ArchiveStatement::Handle {
Handle(void* db, const std::string& statememt) {
if (db == nullptr) {
return;
}
::sqlite3_stmt* handle = nullptr;
if (::sqlite3_prepare_v2(reinterpret_cast<sqlite3*>(db), //
statememt.c_str(), //
static_cast<int>(statememt.size()), //
&handle, //
nullptr) == SQLITE_OK) {
handle_ = handle;
}
}
~Handle() {
if (handle_ == nullptr) {
return;
}
auto res = ::sqlite3_finalize(handle_);
FML_CHECK(res == SQLITE_OK) << "Unable to finalize the archive.";
}
bool IsValid() const { return handle_ != nullptr; }
::sqlite3_stmt* Get() const { return handle_; }
private:
::sqlite3_stmt* handle_ = nullptr;
Handle(const Handle&) = delete;
Handle& operator=(const Handle&) = delete;
};
ArchiveStatement::ArchiveStatement(void* db, const std::string& statememt)
: statement_handle_(std::make_unique<Handle>(db, statememt)) {
if (!statement_handle_->IsValid()) {
statement_handle_.reset();
}
}
ArchiveStatement::~ArchiveStatement() = default;
bool ArchiveStatement::IsValid() const {
return statement_handle_ != nullptr;
}
bool ArchiveStatement::Reset() {
if (!IsValid()) {
return false;
}
if (::sqlite3_reset(statement_handle_->Get()) != SQLITE_OK) {
return false;
}
if (::sqlite3_clear_bindings(statement_handle_->Get()) != SQLITE_OK) {
return false;
}
return true;
}
static constexpr int ToParam(size_t index) {
/*
* sqlite parameters begin from 1
*/
return static_cast<int>(index + 1);
}
static constexpr int ToColumn(size_t index) {
/*
* sqlite columns begin from 0
*/
return static_cast<int>(index);
}
size_t ArchiveStatement::GetColumnCount() {
if (!IsValid()) {
return 0u;
}
return ::sqlite3_column_count(statement_handle_->Get());
}
/*
* Bind Variants
*/
bool ArchiveStatement::WriteValue(size_t index, const std::string& item) {
if (!IsValid()) {
return false;
}
return ::sqlite3_bind_text(statement_handle_->Get(), //
ToParam(index), //
item.data(), //
static_cast<int>(item.size()), //
SQLITE_TRANSIENT) == SQLITE_OK;
}
bool ArchiveStatement::BindIntegral(size_t index, int64_t item) {
if (!IsValid()) {
return false;
}
return ::sqlite3_bind_int64(statement_handle_->Get(), //
ToParam(index), //
item) == SQLITE_OK;
}
bool ArchiveStatement::WriteValue(size_t index, double item) {
if (!IsValid()) {
return false;
}
return ::sqlite3_bind_double(statement_handle_->Get(), //
ToParam(index), //
item) == SQLITE_OK;
}
bool ArchiveStatement::WriteValue(size_t index, const Allocation& item) {
if (!IsValid()) {
return false;
}
return ::sqlite3_bind_blob(statement_handle_->Get(), //
ToParam(index), //
item.GetBuffer(), //
static_cast<int>(item.GetLength()), //
SQLITE_TRANSIENT) == SQLITE_OK;
}
/*
* Column Variants
*/
bool ArchiveStatement::ColumnIntegral(size_t index, int64_t& item) {
if (!IsValid()) {
return false;
}
item = ::sqlite3_column_int64(statement_handle_->Get(), ToColumn(index));
return true;
}
bool ArchiveStatement::ReadValue(size_t index, double& item) {
if (!IsValid()) {
return false;
}
item = ::sqlite3_column_double(statement_handle_->Get(), ToColumn(index));
return true;
}
/*
* For cases where byte sizes of column data is necessary, the
* recommendations in https://www.sqlite.org/c3ref/column_blob.html regarding
* type conversions are followed.
*
* TL;DR: Access blobs then bytes.
*/
bool ArchiveStatement::ReadValue(size_t index, std::string& item) {
if (!IsValid()) {
return false;
}
/*
* Get the character data
*/
auto chars = reinterpret_cast<const char*>(
::sqlite3_column_text(statement_handle_->Get(), ToColumn(index)));
/*
* Get the length of the string (in bytes)
*/
size_t textByteSize =
::sqlite3_column_bytes(statement_handle_->Get(), ToColumn(index));
std::string text(chars, textByteSize);
item.swap(text);
return true;
}
bool ArchiveStatement::ReadValue(size_t index, Allocation& item) {
if (!IsValid()) {
return false;
}
/*
* Get a blob pointer
*/
auto blob = reinterpret_cast<const uint8_t*>(
::sqlite3_column_blob(statement_handle_->Get(), ToColumn(index)));
/*
* Decode the number of bytes in the blob
*/
size_t byteSize =
::sqlite3_column_bytes(statement_handle_->Get(), ToColumn(index));
/*
* Reszie the host allocation and move the blob contents into it
*/
if (!item.Truncate(byteSize, false /* npot */)) {
return false;
}
memmove(item.GetBuffer(), blob, byteSize);
return true;
}
ArchiveStatement::Result ArchiveStatement::Execute() {
if (!IsValid()) {
return Result::kFailure;
}
switch (::sqlite3_step(statement_handle_->Get())) {
case SQLITE_DONE:
return Result::kDone;
case SQLITE_ROW:
return Result::kRow;
default:
return Result::kFailure;
}
}
} // namespace impeller

View File

@ -1,100 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_STATEMENT_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_STATEMENT_H_
#include <memory>
#include <type_traits>
#include "impeller/base/allocation.h"
namespace impeller {
//------------------------------------------------------------------------------
/// @brief Represents a read/write query to an archive database. Statements
/// are expensive to create and must be cached for as long as
/// possible.
///
class ArchiveStatement {
public:
~ArchiveStatement();
bool IsValid() const;
enum class Result {
//--------------------------------------------------------------------------
/// The statement is done executing.
///
kDone,
//--------------------------------------------------------------------------
/// The statement found a row of information ready for reading.
///
kRow,
//--------------------------------------------------------------------------
/// Statement execution was a failure.
///
kFailure,
};
//----------------------------------------------------------------------------
/// @brief Execute the given statement with the provided data.
///
/// @return Is the execution was succeessful.
///
[[nodiscard]] Result Execute();
//----------------------------------------------------------------------------
/// @brief All writes after the last successfull `Run` call are reset.
/// Since statements are expensive to create, reset them for new
/// writes instead of creating new statements.
///
/// @return If the statement writes were reset.
///
bool Reset();
bool WriteValue(size_t index, const std::string& item);
template <class T, class = std::enable_if<std::is_integral<T>::value>>
bool WriteValue(size_t index, T item) {
return BindIntegral(index, static_cast<int64_t>(item));
}
bool WriteValue(size_t index, double item);
bool WriteValue(size_t index, const Allocation& item);
template <class T, class = std::enable_if<std::is_integral<T>::value>>
bool ReadValue(size_t index, T& item) {
return ColumnIntegral(index, item);
}
bool ReadValue(size_t index, double& item);
bool ReadValue(size_t index, std::string& item);
bool ReadValue(size_t index, Allocation& item);
size_t GetColumnCount();
private:
struct Handle;
std::unique_ptr<Handle> statement_handle_;
friend class ArchiveDatabase;
ArchiveStatement(void* db, const std::string& statement);
bool BindIntegral(size_t index, int64_t item);
bool ColumnIntegral(size_t index, int64_t& item);
ArchiveStatement(const ArchiveStatement&) = delete;
ArchiveStatement& operator=(const ArchiveStatement&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_STATEMENT_H_

View File

@ -1,52 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archive_transaction.h"
#include "flutter/fml/logging.h"
#include "impeller/archivist/archive_statement.h"
namespace impeller {
ArchiveTransaction::ArchiveTransaction(int64_t& transactionCount,
ArchiveStatement& beginStatement,
ArchiveStatement& endStatement,
ArchiveStatement& rollbackStatement)
: end_stmt_(endStatement),
rollback_stmt_(rollbackStatement),
transaction_count_(transactionCount) {
if (transaction_count_ == 0) {
cleanup_ = beginStatement.Execute() == ArchiveStatement::Result::kDone;
}
transaction_count_++;
}
ArchiveTransaction::ArchiveTransaction(ArchiveTransaction&& other)
: end_stmt_(other.end_stmt_),
rollback_stmt_(other.rollback_stmt_),
transaction_count_(other.transaction_count_),
cleanup_(other.cleanup_),
successful_(other.successful_) {
other.abandoned_ = true;
}
ArchiveTransaction::~ArchiveTransaction() {
if (abandoned_) {
return;
}
FML_CHECK(transaction_count_ != 0);
if (transaction_count_ == 1 && cleanup_) {
auto res = successful_ ? end_stmt_.Execute() : rollback_stmt_.Execute();
FML_CHECK(res == ArchiveStatement::Result::kDone)
<< "Must be able to commit the nested transaction";
}
transaction_count_--;
}
void ArchiveTransaction::MarkWritesAsReadyForCommit() {
successful_ = true;
}
} // namespace impeller

View File

@ -1,52 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_TRANSACTION_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_TRANSACTION_H_
#include <cstdint>
namespace impeller {
class ArchiveStatement;
//------------------------------------------------------------------------------
/// @brief All writes made to the archive within a transaction that is not
/// marked as ready for commit will be rolled back with the
/// transaction ends.
///
/// All transactions are obtained from the `ArchiveDatabase`.
///
/// @see `ArchiveDatabase`
///
class ArchiveTransaction {
public:
ArchiveTransaction(ArchiveTransaction&& transaction);
~ArchiveTransaction();
void MarkWritesAsReadyForCommit();
private:
ArchiveStatement& end_stmt_;
ArchiveStatement& rollback_stmt_;
int64_t& transaction_count_;
bool cleanup_ = false;
bool successful_ = false;
bool abandoned_ = false;
friend class ArchiveDatabase;
ArchiveTransaction(int64_t& transactionCount,
ArchiveStatement& beginStatement,
ArchiveStatement& endStatement,
ArchiveStatement& rollbackStatement);
ArchiveTransaction(const ArchiveTransaction&) = delete;
ArchiveTransaction& operator=(const ArchiveTransaction&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_TRANSACTION_H_

View File

@ -1,61 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archive_vector.h"
#include <sstream>
#include "impeller/archivist/archive_location.h"
namespace impeller {
ArchiveVector::ArchiveVector(std::vector<int64_t> keys)
: keys_(std::move(keys)) {}
ArchiveVector::ArchiveVector() {}
static constexpr const char* kVectorKeys = "keys";
ArchiveDef ArchiveVector::kArchiveDefinition = {
.table_name = "IPLR_vectors",
.members = {kVectorKeys},
};
PrimaryKey ArchiveVector::GetPrimaryKey() const {
// Archive definition says the keys will be auto assigned.
return std::nullopt;
}
const std::vector<int64_t> ArchiveVector::GetKeys() const {
return keys_;
}
bool ArchiveVector::Write(ArchiveLocation& item) const {
std::stringstream stream;
for (size_t i = 0, count = keys_.size(); i < count; i++) {
stream << keys_[i];
if (i != count - 1) {
stream << ",";
}
}
return item.Write(kVectorKeys, stream.str());
}
bool ArchiveVector::Read(ArchiveLocation& item) {
std::string flattened;
if (!item.Read(kVectorKeys, flattened)) {
return false;
}
std::stringstream stream(flattened);
int64_t single = 0;
while (stream >> single) {
keys_.emplace_back(single);
stream.ignore();
}
return true;
}
} // namespace impeller

View File

@ -1,40 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_VECTOR_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_VECTOR_H_
#include "impeller/archivist/archive.h"
namespace impeller {
class ArchiveVector : public Archivable {
public:
static ArchiveDef kArchiveDefinition;
PrimaryKey GetPrimaryKey() const override;
const std::vector<int64_t> GetKeys() const;
bool Write(ArchiveLocation& item) const override;
bool Read(ArchiveLocation& item) override;
private:
std::vector<int64_t> keys_;
friend class ArchiveLocation;
ArchiveVector();
explicit ArchiveVector(std::vector<int64_t> keys);
ArchiveVector(const ArchiveVector&) = delete;
ArchiveVector& operator=(const ArchiveVector&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVE_VECTOR_H_

View File

@ -1,41 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/archivist/archivist_fixture.h"
#include "flutter/fml/paths.h"
namespace impeller {
namespace testing {
ArchivistFixture::ArchivistFixture() {
std::stringstream stream;
stream << "Test" << flutter::testing::GetCurrentTestName() << ".db";
archive_file_name_ = stream.str();
}
ArchivistFixture::~ArchivistFixture() = default;
const std::string ArchivistFixture::GetArchiveFileName() const {
return fml::paths::JoinPaths(
{flutter::testing::GetFixturesPath(), archive_file_name_});
}
void ArchivistFixture::SetUp() {
DeleteArchiveFile();
}
void ArchivistFixture::TearDown() {
DeleteArchiveFile();
}
void ArchivistFixture::DeleteArchiveFile() const {
auto fixtures = flutter::testing::OpenFixturesDirectory();
if (fml::FileExists(fixtures, archive_file_name_.c_str())) {
fml::UnlinkFile(fixtures, archive_file_name_.c_str());
}
}
} // namespace testing
} // namespace impeller

View File

@ -1,41 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_ARCHIVIST_ARCHIVIST_FIXTURE_H_
#define FLUTTER_IMPELLER_ARCHIVIST_ARCHIVIST_FIXTURE_H_
#include "flutter/fml/macros.h"
#include "flutter/testing/testing.h"
namespace impeller {
namespace testing {
class ArchivistFixture : public ::testing::Test {
public:
ArchivistFixture();
~ArchivistFixture();
// |::testing::Test|
void SetUp() override;
// |::testing::Test|
void TearDown() override;
const std::string GetArchiveFileName() const;
private:
std::string archive_file_name_;
void DeleteArchiveFile() const;
ArchivistFixture(const ArchivistFixture&) = delete;
ArchivistFixture& operator=(const ArchivistFixture&) = delete;
};
} // namespace testing
} // namespace impeller
#endif // FLUTTER_IMPELLER_ARCHIVIST_ARCHIVIST_FIXTURE_H_

View File

@ -1,209 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdio>
#include <thread>
#include "flutter/fml/macros.h"
#include "flutter/testing/testing.h"
#include "impeller/archivist/archive.h"
#include "impeller/archivist/archive_location.h"
#include "impeller/archivist/archivist_fixture.h"
// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
// NOLINTBEGIN(bugprone-unchecked-optional-access)
namespace impeller {
namespace testing {
static int64_t LastSample = 0;
class Sample : public Archivable {
public:
explicit Sample(uint64_t count = 42) : some_data_(count) {}
Sample(Sample&&) = default;
uint64_t GetSomeData() const { return some_data_; }
// |Archivable|
PrimaryKey GetPrimaryKey() const override { return name_; }
// |Archivable|
bool Write(ArchiveLocation& item) const override {
return item.Write("some_data", some_data_);
};
// |Archivable|
bool Read(ArchiveLocation& item) override {
name_ = item.GetPrimaryKey();
return item.Read("some_data", some_data_);
};
static const ArchiveDef kArchiveDefinition;
private:
uint64_t some_data_;
PrimaryKey name_ = ++LastSample;
Sample(const Sample&) = delete;
Sample& operator=(const Sample&) = delete;
};
const ArchiveDef Sample::kArchiveDefinition = {
.table_name = "Sample",
.members = {"some_data"},
};
class SampleWithVector : public Archivable {
public:
SampleWithVector() = default;
// |Archivable|
PrimaryKey GetPrimaryKey() const override { return std::nullopt; }
// |Archivable|
bool Write(ArchiveLocation& item) const override {
std::vector<Sample> samples;
for (size_t i = 0; i < 50u; i++) {
samples.emplace_back(Sample{1988 + i});
}
return item.Write("hello", "world") && item.Write("samples", samples);
};
// |Archivable|
bool Read(ArchiveLocation& item) override {
std::string str;
auto str_result = item.Read("hello", str);
std::vector<Sample> samples;
auto vec_result = item.Read("samples", samples);
if (!str_result || str != "world" || !vec_result || samples.size() != 50) {
return false;
}
size_t current = 1988;
for (const auto& sample : samples) {
if (sample.GetSomeData() != current++) {
return false;
}
}
return true;
};
static const ArchiveDef kArchiveDefinition;
private:
std::vector<Sample> samples_;
SampleWithVector(const SampleWithVector&) = delete;
SampleWithVector& operator=(const SampleWithVector&) = delete;
};
const ArchiveDef SampleWithVector::kArchiveDefinition = {
.table_name = "SampleWithVector",
.members = {"hello", "samples"},
};
using ArchiveTest = ArchivistFixture;
TEST_F(ArchiveTest, SimpleInitialization) {
Archive archive(GetArchiveFileName().c_str());
ASSERT_TRUE(archive.IsValid());
}
TEST_F(ArchiveTest, AddStorageClass) {
Archive archive(GetArchiveFileName().c_str());
ASSERT_TRUE(archive.IsValid());
}
TEST_F(ArchiveTest, AddData) {
Archive archive(GetArchiveFileName().c_str());
ASSERT_TRUE(archive.IsValid());
Sample sample;
ASSERT_TRUE(archive.Write(sample));
}
TEST_F(ArchiveTest, AddDataMultiple) {
Archive archive(GetArchiveFileName().c_str());
ASSERT_TRUE(archive.IsValid());
for (size_t i = 0; i < 100; i++) {
Sample sample(i + 1);
ASSERT_TRUE(archive.Write(sample));
}
}
TEST_F(ArchiveTest, ReadData) {
Archive archive(GetArchiveFileName().c_str());
ASSERT_TRUE(archive.IsValid());
size_t count = 50;
std::vector<PrimaryKey::value_type> keys;
std::vector<uint64_t> values;
for (size_t i = 0; i < count; i++) {
Sample sample(i + 1);
keys.push_back(sample.GetPrimaryKey().value());
values.push_back(sample.GetSomeData());
ASSERT_TRUE(archive.Write(sample));
}
for (size_t i = 0; i < count; i++) {
Sample sample;
ASSERT_TRUE(archive.Read(keys[i], sample));
ASSERT_EQ(values[i], sample.GetSomeData());
}
}
TEST_F(ArchiveTest, ReadDataWithNames) {
Archive archive(GetArchiveFileName().c_str());
ASSERT_TRUE(archive.IsValid());
size_t count = 8;
std::vector<PrimaryKey::value_type> keys;
std::vector<uint64_t> values;
keys.reserve(count);
values.reserve(count);
for (size_t i = 0; i < count; i++) {
Sample sample(i + 1);
keys.push_back(sample.GetPrimaryKey().value());
values.push_back(sample.GetSomeData());
ASSERT_TRUE(archive.Write(sample));
}
for (size_t i = 0; i < count; i++) {
Sample sample;
ASSERT_TRUE(archive.Read(keys[i], sample));
ASSERT_EQ(values[i], sample.GetSomeData());
ASSERT_EQ(keys[i], sample.GetPrimaryKey());
}
}
TEST_F(ArchiveTest, CanReadWriteVectorOfArchivables) {
Archive archive(GetArchiveFileName().c_str());
ASSERT_TRUE(archive.IsValid());
SampleWithVector sample_with_vector;
ASSERT_TRUE(archive.Write(sample_with_vector));
bool read_success = false;
ASSERT_EQ(
archive.Read<SampleWithVector>([&](ArchiveLocation& location) -> bool {
SampleWithVector other_sample_with_vector;
read_success = other_sample_with_vector.Read(location);
return true; // Always keep continuing but assert that we only get one.
}),
1u);
ASSERT_TRUE(read_success);
}
} // namespace testing
} // namespace impeller
// NOLINTEND(bugprone-unchecked-optional-access)

View File

@ -233,7 +233,6 @@ impeller_component("entity") {
":entity_shaders",
":framebuffer_blend_entity_shaders",
":modern_entity_shaders",
"../archivist",
"../image:image_skia_backend",
"../renderer",
"../typographer",