Files
ECAP_Server/module/Local_Server/Data_Source/Database.h
T
2026-08-09 22:00:30 +08:00

182 lines
6.0 KiB
C++

#pragma once
#include <functional>
#include <memory>
#include <shared_mutex>
#include <string_view>
#include <unordered_map>
#include <vector>
#include "../Aircraft/Aircraft.h"
#include "../Aircraft/Flight_VTO.h"
#include "../External_Database/export.h"
#include "Base_Station.h"
#include "Local_Server/server/With_Loop_Coro.h"
template <
typename Key_Type,
typename Value_Type,
size_t Shard_Count = 64
>
struct Data_Map {
using Ptr = std::shared_ptr<Value_Type>;
size_t size() const {
size_t ret = 0;
for (const auto& shard : shards) {
std::shared_lock<std::shared_mutex> g(shard.mtx);
ret += shard.map.size();
}
return ret;
}
Ptr get(const Key_Type& key) const {
const auto& shard = get_shard(key);
std::shared_lock<std::shared_mutex> g(shard.mtx);
auto iter = shard.map.find(key);
if (iter == shard.map.end()) {
return nullptr;
}
return iter->second;
}
Ptr create(const Key_Type& key) {
auto& shard = get_shard(key);
{
std::shared_lock<std::shared_mutex> g(shard.mtx);
auto iter = shard.map.find(key);
if (iter != shard.map.end()) {
return iter->second;
}
}
// 构造对象放锁外,避免构造期间占锁
auto new_value = std::make_shared<Value_Type>(key);
{
std::unique_lock<std::shared_mutex> g(shard.mtx);
auto [iter, inserted] = shard.map.emplace(key, new_value);
// 如果别的线程已经创建了,返回已有对象
return iter->second;
}
}
void remove(const Key_Type& key) {
auto& shard = get_shard(key);
std::unique_lock<std::shared_mutex> g(shard.mtx);
shard.map.erase(key);
}
std::vector<Ptr> values() const {
std::vector<Ptr> ret;
for (const auto& shard : shards) {
std::shared_lock<std::shared_mutex> g(shard.mtx);
for (const auto& [key, val] : shard.map) {
ret.push_back(val);
}
}
return ret;
}
template <typename Cond>
std::vector<Ptr> get_cond(Cond&& cond) const {
std::vector<Ptr> ret;
for (const auto& shard : shards) {
std::vector<Ptr> snapshot;
{
std::shared_lock<std::shared_mutex> g(shard.mtx);
snapshot.reserve(shard.map.size());
for (const auto& [key, val] : shard.map) {
snapshot.push_back(val);
}
}
// cond 放锁外执行
for (const auto& val : snapshot) {
if (cond(val)) {
ret.push_back(val);
}
}
}
return ret;
}
template <typename Cond>
void remove_cond(Cond&& cond) {
for (auto& shard : shards) {
std::vector<std::pair<Key_Type, Ptr>> snapshot;
{
std::shared_lock<std::shared_mutex> g(shard.mtx);
snapshot.reserve(shard.map.size());
for (const auto& [key, val] : shard.map) {
snapshot.emplace_back(key, val);
}
}
std::vector<std::pair<Key_Type, Ptr>> need_remove;
// cond 放锁外执行
for (const auto& [key, val] : snapshot) {
if (cond(val)) {
need_remove.emplace_back(key, val);
}
}
if (need_remove.empty()) {
continue;
}
{
std::unique_lock<std::shared_mutex> g(shard.mtx);
for (const auto& [key, old_val] : need_remove) {
auto iter = shard.map.find(key);
if (iter == shard.map.end()) {
continue;
}
// 防止同 key 已经被换成新对象,误删
if (iter->second == old_val) {
shard.map.erase(iter);
}
}
}
}
}
void delete_all() {
for (auto& shard : shards) {
std::unique_lock<std::shared_mutex> g(shard.mtx);
shard.map.clear();
}
}
protected:
struct Shard {
mutable std::shared_mutex mtx;
std::unordered_map<Key_Type, Ptr> map;
};
Shard& get_shard(const Key_Type& key) {
const size_t index = hasher(key) % Shard_Count;
return shards[index];
}
const Shard& get_shard(const Key_Type& key) const {
const size_t index = hasher(key) % Shard_Count;
return shards[index];
}
protected:
std::hash<Key_Type> hasher;
Shard shards[Shard_Count];
};
class DataBase : public SSR::Data_Source_Interface, public With_Loop_Coro {
public:
std::shared_ptr<SSR::Aircraft_Info> get_aircraft(std::string_view icao) override;
std::shared_ptr<SSR::Aircraft_Info> create_aircraft(std::string_view icao) override;
Psc::JSON get_aircraftlist();
Psc::JSON get_aircraftlist(int limit_msg_num);
Base_Station base_station;
void delete_timeout_aircraft();
std::string get_key() override {
return key;
}
std::atomic<size_t> have_pos_aircraft_num{};
std::vector<std::shared_ptr<SSR::Aircraft_Info>> get_visible_aircraft_snapshot();
std::uint64_t aircraft_change_version(SSR::Aircraft_Info* info);
Psc::JSON aircraft_change_item_json(SSR::Aircraft_Info* info);
Psc::JSON get_aircraft_change_update_json(std::unordered_map<std::string, std::string>& client_versions);
Psc::JSON get_aircraft_list_after(time_t timestamp);
#ifdef Cache_Some_Mode_S
Psc::JSON get_limit_mode_s_msg_info();
#endif
size_t get_aircraft_num();
void clear_aircraft() {
aircraft_map.delete_all();
}
~DataBase() override {
aircraft_map.delete_all();
}
protected:
Data_Map<std::string, Aircraft> aircraft_map;
};
struct Mode_S_Msg;
void database_server(Global* g);