linux 编译

This commit is contained in:
2026-07-13 15:17:20 +08:00
parent 343414650e
commit 92ceeaa908
8 changed files with 10575 additions and 10181 deletions
@@ -20,37 +20,37 @@
#include <string_view>
namespace {
Psc::JSON
external_resource_status_to_json(const External_Resource_Status &status) {
return Psc::JSON::object({
Psc::JSON
external_resource_status_to_json(const External_Resource_Status &status) {
return Psc::JSON::object({
{"name", status.name},
{"row_count", status.row_count},
{"downloaded", status.downloaded},
{"imported", status.imported},
{"message", status.message},
});
}
Psc::JSON external_resource_status_list_to_json(
const std::vector<External_Resource_Status> &status_list) {
auto result = Psc::JSON::array();
for (const auto &status : status_list) {
result.append(external_resource_status_to_json(status));
});
}
return result;
}
trantor::ConcurrentTaskQueue &external_database_task_queue() {
static trantor::ConcurrentTaskQueue queue(2, "external_database");
return queue;
}
Psc::JSON external_resource_status_list_to_json(
const std::vector<External_Resource_Status> &status_list) {
auto result = Psc::JSON::array();
for (const auto &status: status_list) {
result.append(external_resource_status_to_json(status));
}
return result;
}
template <typename T, typename Work, typename Callback>
void run_external_database_async(Work &&work, Callback &&callback) {
auto callback_holder = std::make_shared<std::decay_t<Callback>>(
trantor::ConcurrentTaskQueue &external_database_task_queue() {
static trantor::ConcurrentTaskQueue queue(2, "external_database");
return queue;
}
template<typename T, typename Work, typename Callback>
void run_external_database_async(Work &&work, Callback &&callback) {
auto callback_holder = std::make_shared<std::decay_t<Callback> >(
std::forward<Callback>(callback));
external_database_task_queue().runTaskInQueue(
external_database_task_queue().runTaskInQueue(
[work = std::forward<Work>(work), callback_holder]() mutable {
try {
(*callback_holder)(nullptr, work());
@@ -58,11 +58,11 @@ void run_external_database_async(Work &&work, Callback &&callback) {
(*callback_holder)(std::current_exception(), T{});
}
});
}
}
template <typename T, typename Starter>
asio::awaitable<T> await_external_database_callback(Starter starter) {
auto result = co_await Psc::coro::callback_result<T>(
template<typename T, typename Starter>
asio::awaitable<T> await_external_database_callback(Starter starter) {
auto result = co_await Psc::coro::callback_result<T>(
[starter = std::move(starter)](auto done) mutable {
starter([done = std::move(done)](std::exception_ptr exception,
T value) mutable {
@@ -73,8 +73,8 @@ asio::awaitable<T> await_external_database_callback(Starter starter) {
done(std::move(value));
});
});
co_return std::move(result);
}
co_return std::move(result);
}
} // namespace
std::optional<std::string>
@@ -85,20 +85,20 @@ External_Database_Row::get(std::string_view column) const {
Psc::JSON External_Database_Row::to_json() const {
auto result = Psc::JSON::object();
for (const auto &[column, value] : columns) {
for (const auto &[column, value]: columns) {
result.append({column, value ? Psc::JSON(*value) : Psc::JSON(nullptr)});
}
return result;
}
External_Resources::External_Resources(
std::string_view name, std::string_view cache_file_name, std::string_view download_url,
std::string_view description, const std::uint64_t update_interval_seconds) {
this->name = std::string(name);
this->cache_file_name = std::string(cache_file_name);
this->download_url = std::string(download_url);
this->description = std::string(description);
this->update_interval_seconds = update_interval_seconds;
std::string_view name, std::string_view cache_file_name, std::string_view download_url,
std::string_view description, const std::uint64_t update_interval_seconds) {
this->name = std::string(name);
this->cache_file_name = std::string(cache_file_name);
this->download_url = std::string(download_url);
this->description = std::string(description);
this->update_interval_seconds = update_interval_seconds;
}
void External_Resources::mark_updated() {
@@ -109,9 +109,9 @@ void External_Resources::clear_last_updated_at() { last_updated_at = 0; }
std::size_t External_Resources::row_count(SQLite::Database &db) const {
return static_cast<std::size_t>(
db.execAndGet("SELECT COUNT(*) FROM " +
External_Database_Utils::quote_identifier(name))
.getInt64());
db.execAndGet("SELECT COUNT(*) FROM " +
External_Database_Utils::quote_identifier(name))
.getInt64());
}
std::filesystem::path
@@ -130,16 +130,17 @@ bool External_Resources::fetch(const std::filesystem::path &cache_pos,
return true;
}
External_Resource_Status External_Resources::update(
SQLite::Database &db, const std::filesystem::path &cache_pos,
const bool force_download, const bool only_when_empty) {
External_Resource_Status External_Resources::update(SQLite::Database &db, const std::filesystem::path &cache_pos,
const bool force_download, const bool only_when_empty) {
create_table(db);
External_Resource_Status result{name, row_count(db), false, false, ""};
if (only_when_empty && result.row_count != 0) {
result.message = "table already populated";
return result;
}
if (cache_pos.empty()) {
throw std::invalid_argument("cache_pos is empty");
}
std::filesystem::create_directories(cache_pos);
result.downloaded = fetch(cache_pos, force_download);
if (cache_file_name.empty()) {
@@ -149,8 +150,8 @@ External_Resource_Status External_Resources::update(
const auto local_file = source_file(cache_pos);
if (!std::filesystem::exists(local_file)) {
result.message = download_url.empty()
? "offline import or dynamic query required"
: "cache file unavailable";
? "offline import or dynamic query required"
: "cache file unavailable";
return result;
}
@@ -196,12 +197,12 @@ External_Resources::clear_table(SQLite::Database &db,
}
std::optional<External_Database_Row> External_Resources::query_one(
SQLite::Database &db,
const std::vector<std::string> &primary_key_values) const {
SQLite::Database &db,
const std::vector<std::string> &primary_key_values) const {
const auto &columns = primary_key_columns();
if (columns.size() != primary_key_values.size()) {
throw std::invalid_argument(
"primary key value count mismatch for resource: " + name);
"primary key value count mismatch for resource: " + name);
}
std::string sql = "SELECT * FROM " +
@@ -210,15 +211,15 @@ std::optional<External_Database_Row> External_Resources::query_one(
if (index != 0)
sql += " AND ";
sql += External_Database_Utils::quote_identifier(columns[index]) +
" = ? COLLATE NOCASE";
" = ? COLLATE NOCASE";
}
sql += " LIMIT 1";
SQLite::Statement statement(db, sql);
for (std::size_t index = 0; index < primary_key_values.size(); ++index) {
statement.bind(
static_cast<int>(index + 1),
External_Database_Utils::normalize_key(primary_key_values[index]));
static_cast<int>(index + 1),
External_Database_Utils::normalize_key(primary_key_values[index]));
}
if (!statement.executeStep())
return std::nullopt;
@@ -256,11 +257,11 @@ void External_Resources_Manager::init(const Psc::JSON *that_json) {
if (!list)
return;
std::lock_guard lock(mtx_);
for (const auto &config : list->children) {
for (const auto &config: list->children) {
const auto name = config.try_get_string("name");
if (!name)
continue;
for (const auto &resource : resources_) {
for (const auto &resource: resources_) {
if (resource->name != *name)
continue;
resource->init(&config);
@@ -273,8 +274,9 @@ void External_Resources_Manager::init(const Psc::JSON *that_json) {
Psc::JSON External_Resources_Manager::to_base_json() const {
std::lock_guard lock(mtx_);
auto ret = Psc::JSON::object();
Ret_J(ecap_sqlite_path) auto list = Psc::JSON::array();
for (const std::unique_ptr<External_Resources> &resource : resources_) {
Ret_J(ecap_sqlite_path)
auto list = Psc::JSON::array();
for (const std::unique_ptr<External_Resources> &resource: resources_) {
list.children.emplace_back(resource->to_json());
}
ret.children.emplace_back(Psc::JSON{"list", list});
@@ -284,56 +286,58 @@ Psc::JSON External_Resources_Manager::to_base_json() const {
void External_Resources_Manager::load_sqlite_db(std::string_view path) {
try {
db_ = std::make_unique<SQLite::Database>(path, SQLite::OPEN_READWRITE |
SQLite::OPEN_CREATE);
SQLite::OPEN_CREATE);
} catch (SQLite::Exception &error) {
Psc::fail_fast(std::string("load_sqlite_db error: ") + error.what());
}
db_->exec("PRAGMA journal_mode=WAL;");
db_->exec("PRAGMA synchronous=NORMAL;");
initialize(*db_, std::filesystem::path(path).parent_path());
auto pos = std::filesystem::path(path).parent_path();
// std::cout << "path" << path << " " << pos;
initialize(*db_, pos);
sync_missing(*db_);
}
std::vector<External_Resource_Status>
External_Resources_Manager::refresh_external_databases(
const bool force_download) {
const bool force_download) {
return refresh_all(require_db(), force_download);
}
External_Resource_Status External_Resources_Manager::refresh_external_database(
std::string_view resource_name, const bool force_download) {
std::string_view resource_name, const bool force_download) {
return refresh_one(require_db(), resource_name, force_download);
}
External_Resource_Status External_Resources_Manager::import_external_database(
std::string_view resource_name,
const std::filesystem::path &source_file) {
std::string_view resource_name,
const std::filesystem::path &source_file) {
return import_offline(require_db(), resource_name, source_file);
}
External_Resource_Status
External_Resources_Manager::clear_external_database_table(
std::string_view resource_name) {
std::string_view resource_name) {
return clear_table(require_db(), resource_name);
}
std::optional<External_Database_Row>
External_Resources_Manager::query_external_database(
std::string_view resource_name,
const std::vector<std::string> &primary_key_values) const {
std::string_view resource_name,
const std::vector<std::string> &primary_key_values) const {
return query_one(require_db(), resource_name, primary_key_values);
}
std::map<std::string, std::shared_ptr<External_Database_Row>>
std::map<std::string, std::shared_ptr<External_Database_Row> >
External_Resources_Manager::query_aircraft_external_databases(
std::string_view icao24) const {
std::string_view icao24) const {
return query_aircraft(require_db(), icao24);
}
std::map<std::string, std::shared_ptr<External_Database_Row>>
std::map<std::string, std::shared_ptr<External_Database_Row> >
External_Resources_Manager::query_callsign_external_databases(
const std::optional<std::string> &callsign) const {
const std::optional<std::string> &callsign) const {
return query_callsign(require_db(), callsign);
}
@@ -343,189 +347,189 @@ External_Resources_Manager::external_database_status() const {
}
void External_Resources_Manager::async_refresh_external_databases(
const bool force_download, Status_List_Callback callback) {
run_external_database_async<std::vector<External_Resource_Status>>(
[this, force_download]() {
return refresh_external_databases(force_download);
},
std::move(callback));
const bool force_download, Status_List_Callback callback) {
run_external_database_async<std::vector<External_Resource_Status> >(
[this, force_download]() {
return refresh_external_databases(force_download);
},
std::move(callback));
}
void External_Resources_Manager::async_refresh_external_database(
std::string_view resource_name, const bool force_download,
Status_Callback callback) {
std::string_view resource_name, const bool force_download,
Status_Callback callback) {
run_external_database_async<External_Resource_Status>(
[this, resource_name = std::move(resource_name), force_download]() {
return refresh_external_database(resource_name, force_download);
},
std::move(callback));
[this, resource_name = std::move(resource_name), force_download]() {
return refresh_external_database(resource_name, force_download);
},
std::move(callback));
}
void External_Resources_Manager::async_import_external_database(
std::string_view resource_name, std::filesystem::path source_file,
Status_Callback callback) {
std::string_view resource_name, std::filesystem::path source_file,
Status_Callback callback) {
run_external_database_async<External_Resource_Status>(
[this, resource_name = std::move(resource_name),
source_file = std::move(source_file)]() {
return import_external_database(resource_name, source_file);
},
std::move(callback));
[this, resource_name = std::move(resource_name),
source_file = std::move(source_file)]() {
return import_external_database(resource_name, source_file);
},
std::move(callback));
}
void External_Resources_Manager::async_clear_external_database_table(
std::string_view resource_name, Status_Callback callback) {
std::string_view resource_name, Status_Callback callback) {
run_external_database_async<External_Resource_Status>(
[this, resource_name = std::move(resource_name)]() {
return clear_external_database_table(resource_name);
},
std::move(callback));
[this, resource_name = std::move(resource_name)]() {
return clear_external_database_table(resource_name);
},
std::move(callback));
}
void External_Resources_Manager::async_query_external_database(
std::string_view resource_name, std::vector<std::string> primary_key_values,
Row_Callback callback) const {
run_external_database_async<std::optional<External_Database_Row>>(
[this, resource_name = std::move(resource_name),
primary_key_values = std::move(primary_key_values)]() {
return query_external_database(resource_name, primary_key_values);
},
std::move(callback));
std::string_view resource_name, std::vector<std::string> primary_key_values,
Row_Callback callback) const {
run_external_database_async<std::optional<External_Database_Row> >(
[this, resource_name = std::move(resource_name),
primary_key_values = std::move(primary_key_values)]() {
return query_external_database(resource_name, primary_key_values);
},
std::move(callback));
}
void External_Resources_Manager::async_query_aircraft_external_databases(
std::string_view icao24, Row_Map_Callback callback) const {
std::string_view icao24, Row_Map_Callback callback) const {
run_external_database_async<
std::map<std::string, std::shared_ptr<External_Database_Row>>>(
[this, icao24 = std::move(icao24)]() {
return query_aircraft_external_databases(icao24);
},
std::move(callback));
std::map<std::string, std::shared_ptr<External_Database_Row> > >(
[this, icao24 = std::move(icao24)]() {
return query_aircraft_external_databases(icao24);
},
std::move(callback));
}
void External_Resources_Manager::async_query_callsign_external_databases(
std::optional<std::string> callsign, Row_Map_Callback callback) const {
std::optional<std::string> callsign, Row_Map_Callback callback) const {
run_external_database_async<
std::map<std::string, std::shared_ptr<External_Database_Row>>>(
[this, callsign = std::move(callsign)]() {
return query_callsign_external_databases(callsign);
},
std::move(callback));
std::map<std::string, std::shared_ptr<External_Database_Row> > >(
[this, callsign = std::move(callsign)]() {
return query_callsign_external_databases(callsign);
},
std::move(callback));
}
void External_Resources_Manager::async_external_database_status(
Status_List_Callback callback) const {
run_external_database_async<std::vector<External_Resource_Status>>(
[this]() { return external_database_status(); }, std::move(callback));
Status_List_Callback callback) const {
run_external_database_async<std::vector<External_Resource_Status> >(
[this]() { return external_database_status(); }, std::move(callback));
}
asio::awaitable<std::vector<External_Resource_Status>>
asio::awaitable<std::vector<External_Resource_Status> >
External_Resources_Manager::refresh_external_databases_coro(
const bool force_download) {
const bool force_download) {
co_return co_await await_external_database_callback<
std::vector<External_Resource_Status>>(
[this, force_download](Status_List_Callback callback) {
async_refresh_external_databases(force_download, std::move(callback));
});
std::vector<External_Resource_Status> >(
[this, force_download](Status_List_Callback callback) {
async_refresh_external_databases(force_download, std::move(callback));
});
}
asio::awaitable<External_Resource_Status>
External_Resources_Manager::refresh_external_database_coro(
std::string_view resource_name, const bool force_download) {
std::string_view resource_name, const bool force_download) {
co_return co_await await_external_database_callback<External_Resource_Status>(
[this, resource_name = std::move(resource_name),
force_download](Status_Callback callback) mutable {
async_refresh_external_database(std::move(resource_name),
force_download, std::move(callback));
});
[this, resource_name = std::move(resource_name),
force_download](Status_Callback callback) mutable {
async_refresh_external_database(std::move(resource_name),
force_download, std::move(callback));
});
}
asio::awaitable<External_Resource_Status>
External_Resources_Manager::import_external_database_coro(
std::string_view resource_name, std::filesystem::path source_file) {
std::string_view resource_name, std::filesystem::path source_file) {
co_return co_await await_external_database_callback<External_Resource_Status>(
[this, resource_name = std::move(resource_name),
source_file = std::move(source_file)](Status_Callback callback) mutable {
async_import_external_database(std::move(resource_name),
std::move(source_file),
std::move(callback));
});
[this, resource_name = std::move(resource_name),
source_file = std::move(source_file)](Status_Callback callback) mutable {
async_import_external_database(std::move(resource_name),
std::move(source_file),
std::move(callback));
});
}
asio::awaitable<External_Resource_Status>
External_Resources_Manager::clear_external_database_table_coro(
std::string_view resource_name) {
std::string_view resource_name) {
co_return co_await await_external_database_callback<External_Resource_Status>(
[this, resource_name =
std::move(resource_name)](Status_Callback callback) mutable {
async_clear_external_database_table(std::move(resource_name),
std::move(callback));
});
[this, resource_name =
std::move(resource_name)](Status_Callback callback) mutable {
async_clear_external_database_table(std::move(resource_name),
std::move(callback));
});
}
asio::awaitable<std::optional<External_Database_Row>>
asio::awaitable<std::optional<External_Database_Row> >
External_Resources_Manager::query_external_database_coro(
std::string_view resource_name,
std::vector<std::string> primary_key_values) const {
std::string_view resource_name,
std::vector<std::string> primary_key_values) const {
co_return co_await await_external_database_callback<
std::optional<External_Database_Row>>(
[this, resource_name = std::move(resource_name),
primary_key_values =
std::move(primary_key_values)](Row_Callback callback) mutable {
async_query_external_database(std::move(resource_name),
std::move(primary_key_values),
std::move(callback));
});
std::optional<External_Database_Row> >(
[this, resource_name = std::move(resource_name),
primary_key_values =
std::move(primary_key_values)](Row_Callback callback) mutable {
async_query_external_database(std::move(resource_name),
std::move(primary_key_values),
std::move(callback));
});
}
asio::awaitable<std::shared_ptr<External_Database_Row_Map>>
asio::awaitable<std::shared_ptr<External_Database_Row_Map> >
External_Resources_Manager::query_aircraft_external_databases_coro(
std::string_view icao24) const {
std::string_view icao24) const {
auto result = co_await Psc::coro::callback_result<
std::shared_ptr<External_Database_Row_Map>>(
[this, icao24 = std::move(icao24)](auto done) mutable {
async_query_aircraft_external_databases(
std::move(icao24),
[done = std::move(done)](std::exception_ptr exception,
External_Database_Row_Map value) mutable {
if (exception) {
done.set_exception(exception);
return;
}
done(std::make_shared<External_Database_Row_Map>(
std::move(value)));
});
});
std::shared_ptr<External_Database_Row_Map> >(
[this, icao24 = std::move(icao24)](auto done) mutable {
async_query_aircraft_external_databases(
std::move(icao24),
[done = std::move(done)](std::exception_ptr exception,
External_Database_Row_Map value) mutable {
if (exception) {
done.set_exception(exception);
return;
}
done(std::make_shared<External_Database_Row_Map>(
std::move(value)));
});
});
co_return result;
}
asio::awaitable<std::shared_ptr<External_Database_Row_Map>>
asio::awaitable<std::shared_ptr<External_Database_Row_Map> >
External_Resources_Manager::query_callsign_external_databases_coro(
std::optional<std::string> callsign) const {
std::optional<std::string> callsign) const {
auto result = co_await Psc::coro::callback_result<
std::shared_ptr<External_Database_Row_Map>>(
[this, callsign = std::move(callsign)](auto done) mutable {
async_query_callsign_external_databases(
std::move(callsign),
[done = std::move(done)](std::exception_ptr exception,
External_Database_Row_Map value) mutable {
if (exception) {
done.set_exception(exception);
return;
}
done(std::make_shared<External_Database_Row_Map>(
std::move(value)));
});
});
std::shared_ptr<External_Database_Row_Map> >(
[this, callsign = std::move(callsign)](auto done) mutable {
async_query_callsign_external_databases(
std::move(callsign),
[done = std::move(done)](std::exception_ptr exception,
External_Database_Row_Map value) mutable {
if (exception) {
done.set_exception(exception);
return;
}
done(std::make_shared<External_Database_Row_Map>(
std::move(value)));
});
});
co_return result;
}
asio::awaitable<std::vector<External_Resource_Status>>
asio::awaitable<std::vector<External_Resource_Status> >
External_Resources_Manager::external_database_status_coro() const {
co_return co_await await_external_database_callback<
std::vector<External_Resource_Status>>(
[this](Status_List_Callback callback) {
async_external_database_status(std::move(callback));
});
std::vector<External_Resource_Status> >(
[this](Status_List_Callback callback) {
async_external_database_status(std::move(callback));
});
}
void External_Resources_Manager::server(Global *g) {
@@ -538,120 +542,121 @@ void External_Resources_Manager::server(Global *g) {
res->setBody(t);
});
svr.PostCoro(
api + "get_external_database_status",
[this](HTTP_Param) -> drogon::Task<> {
auto status_list =
co_await Ecap_Coro::to_drogon(external_database_status_coro());
api + "get_external_database_status",
[this](HTTP_Param) -> drogon::Task<> {
auto status_list =
co_await Ecap_Coro::to_drogon(external_database_status_coro());
res->setBody(warp(external_resource_status_list_to_json(status_list))
.to_json_string());
co_return;
});
res->setBody(warp(external_resource_status_list_to_json(status_list))
.to_json_string());
co_return;
});
svr.PostCoro(
api + "refresh_external_database",
[this, g](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
const auto result = co_await Ecap_Coro::to_drogon(
refresh_external_database_coro(name, true));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
api + "refresh_external_database",
[this, g](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
const auto result = co_await Ecap_Coro::to_drogon(
refresh_external_database_coro(name, true));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
svr.PostCoro(api + "refresh_external_databases",
[this, g](HTTP_Param) -> drogon::Task<> {
const auto result = co_await Ecap_Coro::to_drogon(
refresh_external_databases_coro(true));
refresh_external_databases_coro(true));
g->save();
res->setBody(
warp(external_resource_status_list_to_json(result))
.to_json_string());
warp(external_resource_status_list_to_json(result))
.to_json_string());
co_return;
});
svr.PostCoro(
api + "import_external_database",
[this, g](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
HTTP_REQUIRE_VALUE(source_file, params.try_get_string("source_file"))
const auto result = co_await Ecap_Coro::to_drogon(
import_external_database_coro(name, source_file));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
api + "import_external_database",
[this, g](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
HTTP_REQUIRE_VALUE(source_file, params.try_get_string("source_file"))
const auto result = co_await Ecap_Coro::to_drogon(
import_external_database_coro(name, source_file));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
svr.PostCoro(
api + "upload_external_database",
[this, g](HTTP_Param) -> drogon::Task<> {
drogon::MultiPartParser parser;
if (parser.parse(req) != 0) {
throw_invalid_http_param("multipart");
}
const auto name = parser.getOptionalParameter<std::string>("name");
if (!name || parser.getFiles().size() != 1) {
throw_invalid_http_param("name or file");
}
api + "upload_external_database",
[this, g](HTTP_Param) -> drogon::Task<> {
drogon::MultiPartParser parser;
if (parser.parse(req) != 0) {
throw_invalid_http_param("multipart");
}
const auto name = parser.getOptionalParameter<std::string>("name");
if (!name || parser.getFiles().size() != 1) {
throw_invalid_http_param("name or file");
}
const auto &upload = parser.getFiles().front();
const auto serial =
std::chrono::steady_clock::now().time_since_epoch().count();
auto extension = std::string(upload.getFileExtension());
if (!extension.empty() && extension.front() != '.') {
extension.insert(extension.begin(), '.');
}
const auto saved_name =
"external_database_" + std::to_string(serial) + extension;
if (upload.saveAs(saved_name) != 0) {
throw std::runtime_error(
"Cannot save uploaded external database file");
}
const auto &upload = parser.getFiles().front();
const auto serial =
std::chrono::steady_clock::now().time_since_epoch().count();
auto extension = std::string(upload.getFileExtension());
if (!extension.empty() && extension.front() != '.') {
extension.insert(extension.begin(), '.');
}
const auto saved_name =
"external_database_" + std::to_string(serial) + extension;
if (upload.saveAs(saved_name) != 0) {
throw std::runtime_error(
"Cannot save uploaded external database file");
}
const auto source_file =
std::filesystem::path(drogon::app().getUploadPath()) / saved_name;
const auto result = co_await Ecap_Coro::to_drogon(
import_external_database_coro(*name, source_file));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
const auto source_file =
std::filesystem::path(drogon::app().getUploadPath()) / saved_name;
const auto result = co_await Ecap_Coro::to_drogon(
import_external_database_coro(*name, source_file));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
svr.PostCoro(
api + "clear_external_database_table",
[this, g](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
const auto result = co_await Ecap_Coro::to_drogon(
clear_external_database_table_coro(name));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
api + "clear_external_database_table",
[this, g](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
const auto result = co_await Ecap_Coro::to_drogon(
clear_external_database_table_coro(name));
g->save();
res->setBody(
warp(external_resource_status_to_json(result)).to_json_string());
co_return;
});
svr.PostCoro(
api + "query_external_database", [this](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
HTTP_REQUIRE_PTR(primary_key_values_json,
params.get("primary_key_values"))
std::vector<std::string> primary_key_values;
for (const auto &value : primary_key_values_json->children) {
if (value.valueType != Psc::JsonType::String) {
throw_invalid_http_param("primary_key_values");
}
primary_key_values.push_back(value.val);
api + "query_external_database", [this](HTTP_Param) -> drogon::Task<> {
CHECK_JSON_PARAM
HTTP_REQUIRE_VALUE(name, params.try_get_string("name"))
HTTP_REQUIRE_PTR(primary_key_values_json,
params.get("primary_key_values"))
std::vector<std::string> primary_key_values;
for (const auto &value: primary_key_values_json->children) {
if (value.valueType != Psc::JsonType::String) {
throw_invalid_http_param("primary_key_values");
}
const auto row = co_await Ecap_Coro::to_drogon(
query_external_database_coro(name, std::move(primary_key_values)));
res->setBody(row ? warp(row->to_json()).to_json_string()
: Psc::JSON(nullptr).to_json_string());
co_return;
});
primary_key_values.push_back(value.val);
}
const auto row = co_await Ecap_Coro::to_drogon(
query_external_database_coro(name, std::move(primary_key_values)));
res->setBody(row
? warp(row->to_json()).to_json_string()
: Psc::JSON(nullptr).to_json_string());
co_return;
});
}
void External_Resources_Manager::register_external_resource(
std::unique_ptr<External_Resources> external_res) {
std::unique_ptr<External_Resources> external_res) {
if (!external_res)
throw std::invalid_argument("external resource is null");
resources_.push_back(std::move(external_res));
@@ -661,7 +666,7 @@ void External_Resources_Manager::initialize(SQLite::Database &db,
std::filesystem::path cache_pos) {
std::lock_guard lock(mtx_);
cache_pos_ = std::move(cache_pos);
for (const auto &resource : resources_)
for (const auto &resource: resources_)
resource->create_table(db);
}
@@ -686,8 +691,8 @@ External_Resources_Manager::refresh_one(SQLite::Database &db,
}
External_Resource_Status External_Resources_Manager::import_offline(
SQLite::Database &db, std::string_view resource_name,
const std::filesystem::path &source_file) {
SQLite::Database &db, std::string_view resource_name,
const std::filesystem::path &source_file) {
std::lock_guard lock(mtx_);
return get_resource(resource_name).import_offline(db, source_file);
}
@@ -700,25 +705,25 @@ External_Resources_Manager::clear_table(SQLite::Database &db,
}
std::optional<External_Database_Row> External_Resources_Manager::query_one(
SQLite::Database &db, std::string_view resource_name,
const std::vector<std::string> &primary_key_values) const {
SQLite::Database &db, std::string_view resource_name,
const std::vector<std::string> &primary_key_values) const {
std::lock_guard lock(mtx_);
return get_resource(resource_name).query_one(db, primary_key_values);
}
std::map<std::string, std::shared_ptr<External_Database_Row>>
std::map<std::string, std::shared_ptr<External_Database_Row> >
External_Resources_Manager::query_aircraft(SQLite::Database &db,
std::string_view icao24) const {
Scope_Timer timer(
"external_database.query_aircraft",
Global::instance()->http_monitor_config.slow_scope_threshold_ms);
"external_database.query_aircraft",
Global::instance()->http_monitor_config.slow_scope_threshold_ms);
static const std::vector<std::string> kAircraftResourceKeys = {
"tar1090_db_aircraft", "wiedehopf_tar1090_db_aircraft",
"mictronics_aircraft_database", "opensky_aircraft_database",
"faa_aircraft_registry",
"tar1090_db_aircraft", "wiedehopf_tar1090_db_aircraft",
"mictronics_aircraft_database", "opensky_aircraft_database",
"faa_aircraft_registry",
};
std::lock_guard lock(mtx_);
std::map<std::string, std::shared_ptr<External_Database_Row>> result;
std::map<std::string, std::shared_ptr<External_Database_Row> > result;
const auto add_row = [&](std::string_view resource_name,
const std::vector<std::string> &primary_key_values,
std::string_view result_name = std::string{}) {
@@ -733,7 +738,7 @@ External_Resources_Manager::query_aircraft(SQLite::Database &db,
};
std::optional<std::string> type_code;
for (const auto &resource_name : kAircraftResourceKeys) {
for (const auto &resource_name: kAircraftResourceKeys) {
const auto row = add_row(resource_name, std::vector<std::string>{std::string(icao24)});
if (row && !type_code) {
type_code = row->get("type_code");
@@ -747,20 +752,20 @@ External_Resources_Manager::query_aircraft(SQLite::Database &db,
return result;
}
std::map<std::string, std::shared_ptr<External_Database_Row>>
std::map<std::string, std::shared_ptr<External_Database_Row> >
External_Resources_Manager::query_callsign(
SQLite::Database &db, const std::optional<std::string> &callsign) const {
SQLite::Database &db, const std::optional<std::string> &callsign) const {
Scope_Timer timer(
"external_database.query_callsign",
Global::instance()->http_monitor_config.slow_scope_threshold_ms);
"external_database.query_callsign",
Global::instance()->http_monitor_config.slow_scope_threshold_ms);
static const std::vector<std::string> kRouteResourceKeys = {
"vrs_routes",
"adsblol_vrs_standing_data_routes",
"vradarserver_standing_data_routes",
"vrs_routes",
"adsblol_vrs_standing_data_routes",
"vradarserver_standing_data_routes",
};
std::lock_guard lock(mtx_);
std::map<std::string, std::shared_ptr<External_Database_Row>> result;
std::map<std::string, std::shared_ptr<External_Database_Row> > result;
const auto add_row = [&](std::string_view resource_name,
const std::vector<std::string> &primary_key_values,
std::string_view result_name = std::string{}) {
@@ -776,7 +781,7 @@ External_Resources_Manager::query_callsign(
std::set<std::string> airport_codes;
if (callsign && !callsign->empty()) {
for (const auto &resource_name : kRouteResourceKeys) {
for (const auto &resource_name: kRouteResourceKeys) {
const auto row = add_row(resource_name, {*callsign});
if (!row)
continue;
@@ -795,7 +800,7 @@ External_Resources_Manager::query_callsign(
}
}
for (const auto &airport_code : airport_codes) {
for (const auto &airport_code: airport_codes) {
if (airport_code.empty())
continue;
add_row("vrs_airports", {airport_code}, "vrs_airports:" + airport_code);
@@ -807,9 +812,9 @@ std::vector<External_Resource_Status>
External_Resources_Manager::status(SQLite::Database &db) const {
std::lock_guard lock(mtx_);
std::vector<External_Resource_Status> result;
for (const auto &resource : resources_) {
for (const auto &resource: resources_) {
result.push_back(
{resource->name, resource->row_count(db), false, false, ""});
{resource->name, resource->row_count(db), false, false, ""});
}
return result;
}
@@ -822,8 +827,8 @@ SQLite::Database &External_Resources_Manager::require_db() const {
}
External_Resources &External_Resources_Manager::get_resource(
std::string_view resource_name) const {
for (const auto &resource : resources_) {
std::string_view resource_name) const {
for (const auto &resource: resources_) {
if (resource->name == resource_name)
return *resource;
}
@@ -836,18 +841,21 @@ External_Resources_Manager::update_all(SQLite::Database &db,
const bool only_when_empty) {
std::lock_guard lock(mtx_);
std::vector<External_Resource_Status> result;
for (const auto &resource : resources_) {
for (const auto &resource: resources_) {
External_Resource_Status status;
try {
auto status =
status =
resource->update(db, cache_pos_, force_download, only_when_empty);
std::cout << "External database [" << status.name << "] "
<< status.message << ", rows=" << status.row_count << std::endl;
<< status.message << ", rows=" << status.row_count << std::endl;
result.push_back(std::move(status));
} catch (const std::exception &error) {
std::cerr << "External database [" << resource->name
<< "] update failed: " << error.what() << std::endl;
result.push_back({resource->name, resource->row_count(db), false, false,
error.what()});
<< "] update failed: [" << error.what() << "]" << " status.message:" << status.message << std::endl;
result.push_back({
resource->name, resource->row_count(db), false, false,
error.what()
});
}
}
return result;