Cmake и ClientCache
This commit is contained in:
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "Libs/boost"]
|
||||||
|
path = Libs/boost
|
||||||
|
url = https://github.com/boostorg/boost.git
|
||||||
119
CMakeLists.txt
119
CMakeLists.txt
@@ -6,7 +6,6 @@ option(BUILD_CLIENT "Build the client" TRUE)
|
|||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
add_compile_options(-fcoroutines)
|
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -DGLM_FORCE_DEPTH_ZERO_TO_ONE")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -DGLM_FORCE_DEPTH_ZERO_TO_ONE")
|
||||||
@@ -23,12 +22,15 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
|
|||||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment")
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment")
|
||||||
|
|
||||||
project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
||||||
add_executable(${PROJECT_NAME})
|
|
||||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SOURCES RELATIVE ${PROJECT_SOURCE_DIR} "Src/*.cpp")
|
add_library(luavox_common INTERFACE)
|
||||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
target_compile_features(luavox_common INTERFACE cxx_std_20)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Src")
|
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||||
|
target_compile_options(luavox_common INTERFACE -fcoroutines)
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||||
|
target_compile_options(luavox_common INTERFACE -fcoroutine)
|
||||||
|
endif()
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
@@ -51,7 +53,7 @@ FetchContent_Declare(
|
|||||||
DOWNLOAD_NO_EXTRACT FALSE
|
DOWNLOAD_NO_EXTRACT FALSE
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(Boost)
|
FetchContent_MakeAvailable(Boost)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::asio Boost::thread Boost::json)
|
target_link_libraries(luavox_common INTERFACE Boost::asio Boost::thread Boost::json)
|
||||||
|
|
||||||
# glm
|
# glm
|
||||||
# find_package(glm REQUIRED)
|
# find_package(glm REQUIRED)
|
||||||
@@ -64,61 +66,33 @@ FetchContent_Declare(
|
|||||||
GIT_TAG 1.0.1
|
GIT_TAG 1.0.1
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(glm)
|
FetchContent_MakeAvailable(glm)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC glm)
|
target_link_libraries(luavox_common INTERFACE glm)
|
||||||
|
|
||||||
find_package(ICU REQUIRED COMPONENTS i18n uc)
|
find_package(ICU REQUIRED COMPONENTS i18n uc)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${ICU_INCLUDE_DIR})
|
target_include_directories(luavox_common INTERFACE ${ICU_INCLUDE_DIR})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${ICU_LIBRARIES})
|
target_link_libraries(luavox_common INTERFACE ${ICU_LIBRARIES})
|
||||||
|
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${OPENSSL_INCLUDE_DIR})
|
target_include_directories(luavox_common INTERFACE ${OPENSSL_INCLUDE_DIR})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${OPENSSL_LIBRARIES})
|
target_link_libraries(luavox_common INTERFACE ${OPENSSL_LIBRARIES})
|
||||||
|
|
||||||
# JPEG
|
# JPEG
|
||||||
find_package(JPEG REQUIRED)
|
find_package(JPEG REQUIRED)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${JPEG_INCLUDE_DIRS})
|
target_include_directories(luavox_common INTERFACE ${JPEG_INCLUDE_DIRS})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC JPEG::JPEG)
|
target_link_libraries(luavox_common INTERFACE JPEG::JPEG)
|
||||||
|
|
||||||
# PNG
|
# PNG
|
||||||
find_package(PNG REQUIRED)
|
find_package(PNG REQUIRED)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${PNG_INCLUDE_DIRS})
|
target_include_directories(luavox_common INTERFACE ${PNG_INCLUDE_DIRS})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC PNG::PNG)
|
target_link_libraries(luavox_common INTERFACE PNG::PNG)
|
||||||
|
|
||||||
# PNG++
|
# PNG++
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Libs/png++")
|
target_include_directories(luavox_common INTERFACE "${PROJECT_SOURCE_DIR}/Libs/png++")
|
||||||
|
|
||||||
# GLFW3
|
# sqlite3
|
||||||
if(BUILD_CLIENT)
|
FetchContent_Declare(sqlite3 GIT_REPOSITORY https://github.com/sjinks/sqlite3-cmake GIT_TAG v3.49.1)
|
||||||
find_package(glfw3 3)
|
FetchContent_MakeAvailable(sqlite3)
|
||||||
|
target_link_libraries(luavox_common INTERFACE SQLite::SQLite3)
|
||||||
if(TARGET glfw)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GLFW_INCLUDE_DIRS})
|
|
||||||
else()
|
|
||||||
FetchContent_Declare(
|
|
||||||
glfw
|
|
||||||
GIT_REPOSITORY https://github.com/glfw/glfw.git
|
|
||||||
GIT_TAG 3.4
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(glfw)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC glfw)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# FreeType
|
|
||||||
find_package(Freetype REQUIRED)
|
|
||||||
# FetchContent_Declare(
|
|
||||||
# freetype
|
|
||||||
# GIT_REPOSITORY https://github.com/freetype/freetype.git
|
|
||||||
# GIT_TAG freetype
|
|
||||||
# )
|
|
||||||
# FetchContent_MakeAvailable(freetype)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${freetype_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype)
|
|
||||||
|
|
||||||
# ImGui
|
|
||||||
file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/Libs/imgui/*.cpp")
|
|
||||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES} "${PROJECT_SOURCE_DIR}/Libs/imgui/backends/imgui_impl_glfw.cpp" "${PROJECT_SOURCE_DIR}/Libs/imgui/backends/imgui_impl_vulkan.cpp")
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Libs/imgui/")
|
|
||||||
|
|
||||||
# Static Assets
|
# Static Assets
|
||||||
file(GLOB_RECURSE ASSETS RELATIVE "${PROJECT_SOURCE_DIR}/assets" "assets/*.*")
|
file(GLOB_RECURSE ASSETS RELATIVE "${PROJECT_SOURCE_DIR}/assets" "assets/*.*")
|
||||||
@@ -127,7 +101,48 @@ add_custom_command(OUTPUT assets.o resources.cpp INPUT ${ASSETS}
|
|||||||
COMMAND cd "${CMAKE_CURRENT_SOURCE_DIR}/assets" && ld -r -b binary -o '${CMAKE_CURRENT_BINARY_DIR}/assets.o' ${ASSETS}
|
COMMAND cd "${CMAKE_CURRENT_SOURCE_DIR}/assets" && ld -r -b binary -o '${CMAKE_CURRENT_BINARY_DIR}/assets.o' ${ASSETS}
|
||||||
COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/assets.o ${CMAKE_CURRENT_BINARY_DIR}/assets.o)
|
COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/assets.o ${CMAKE_CURRENT_BINARY_DIR}/assets.o)
|
||||||
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED true)
|
set_source_files_properties(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED true)
|
||||||
add_library(assets STATIC resources.cpp assets.o)
|
add_library(assets STATIC resources.cpp assets.o)
|
||||||
SET_TARGET_PROPERTIES(assets PROPERTIES LINKER_LANGUAGE C)
|
set_target_properties(assets PROPERTIES LINKER_LANGUAGE C)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC assets uring)
|
target_link_libraries(luavox_common INTERFACE assets)
|
||||||
|
|
||||||
|
# uring
|
||||||
|
target_link_libraries(luavox_common INTERFACE uring)
|
||||||
|
|
||||||
|
if(BUILD_CLIENT)
|
||||||
|
add_executable(luavox_client)
|
||||||
|
|
||||||
|
# Common
|
||||||
|
target_link_libraries(luavox_client PUBLIC luavox_common)
|
||||||
|
|
||||||
|
# Исходники
|
||||||
|
file(GLOB_RECURSE SOURCES RELATIVE ${PROJECT_SOURCE_DIR} "Src/*.cpp")
|
||||||
|
target_sources(luavox_client PRIVATE ${SOURCES})
|
||||||
|
target_include_directories(luavox_client PUBLIC "${PROJECT_SOURCE_DIR}/Src")
|
||||||
|
|
||||||
|
# GLFW3
|
||||||
|
FetchContent_Declare(
|
||||||
|
glfw
|
||||||
|
GIT_REPOSITORY https://github.com/glfw/glfw.git
|
||||||
|
GIT_TAG 3.4
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(glfw)
|
||||||
|
target_link_libraries(luavox_client PUBLIC glfw)
|
||||||
|
|
||||||
|
# FreeType
|
||||||
|
find_package(Freetype REQUIRED)
|
||||||
|
# FetchContent_Declare(
|
||||||
|
# freetype
|
||||||
|
# GIT_REPOSITORY https://github.com/freetype/freetype.git
|
||||||
|
# GIT_TAG freetype
|
||||||
|
# )
|
||||||
|
# FetchContent_MakeAvailable(freetype)
|
||||||
|
target_include_directories(luavox_client PUBLIC ${freetype_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(luavox_client PUBLIC Freetype::Freetype)
|
||||||
|
|
||||||
|
# ImGui
|
||||||
|
file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/Libs/imgui/*.cpp")
|
||||||
|
target_sources(luavox_client PRIVATE ${SOURCES} "${PROJECT_SOURCE_DIR}/Libs/imgui/backends/imgui_impl_glfw.cpp" "${PROJECT_SOURCE_DIR}/Libs/imgui/backends/imgui_impl_vulkan.cpp")
|
||||||
|
target_include_directories(luavox_client PUBLIC "${PROJECT_SOURCE_DIR}/Libs/imgui/")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|||||||
1
Libs/boost
Submodule
1
Libs/boost
Submodule
Submodule Libs/boost added at c89e626766
7
Src/Client/ResourceCache.cpp
Normal file
7
Src/Client/ResourceCache.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include "ResourceCache.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace LV::Client {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
311
Src/Client/ResourceCache.hpp
Normal file
311
Src/Client/ResourceCache.hpp
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include <TOSLib.hpp>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
|
||||||
|
namespace LV::Client {
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
// NOT ThreadSafe
|
||||||
|
class ResourceCacheHandler {
|
||||||
|
const fs::path Path;
|
||||||
|
|
||||||
|
sqlite3 *DB = nullptr;
|
||||||
|
sqlite3_stmt *STMT_INSERT = nullptr,
|
||||||
|
*STMT_UPDATE_TIME = nullptr,
|
||||||
|
*STMT_REMOVE = nullptr,
|
||||||
|
*STMT_ALL_HASH = nullptr,
|
||||||
|
*STMT_SUM = nullptr,
|
||||||
|
*STMT_TO_FREE = nullptr,
|
||||||
|
*STMT_COUNT = nullptr;
|
||||||
|
|
||||||
|
size_t Size = -1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ResourceCacheHandler(const std::string_view cache_path)
|
||||||
|
: Path(cache_path)
|
||||||
|
{
|
||||||
|
int errc = sqlite3_open_v2((Path / "db.sqlite3").c_str(), &DB, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr);
|
||||||
|
if(errc) {
|
||||||
|
MAKE_ERROR("Не удалось открыть базу данных " << (Path / "db.sqlite3").c_str() << ": " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* sql = R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS files(
|
||||||
|
sha256 BLOB(32) NOT NULL, --
|
||||||
|
last_used INT NOT NULL, -- unix timestamp
|
||||||
|
size INT NOT NULL, -- file size
|
||||||
|
UNIQUE (sha256));
|
||||||
|
)";
|
||||||
|
|
||||||
|
errc = sqlite3_exec(DB, sql, nullptr, nullptr, nullptr);
|
||||||
|
if(errc != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить таблицу базы: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = R"(
|
||||||
|
INSERT OR REPLACE INTO files (sha256, last_used, size)
|
||||||
|
VALUES (?, ?, ?);
|
||||||
|
)";
|
||||||
|
|
||||||
|
if(sqlite3_prepare_v2(DB, sql, -1, &STMT_INSERT, nullptr) != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить запрос STMT_INSERT: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = R"(
|
||||||
|
UPDATE files SET last_used = ? WHERE sha256 = ?;
|
||||||
|
)";
|
||||||
|
|
||||||
|
if(sqlite3_prepare_v2(DB, sql, -1, &STMT_UPDATE_TIME, nullptr) != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить запрос STMT_UPDATE_TIME: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = R"(
|
||||||
|
DELETE FROM files WHERE sha256=?;
|
||||||
|
)";
|
||||||
|
|
||||||
|
if(sqlite3_prepare_v2(DB, sql, -1, &STMT_REMOVE, nullptr) != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить запрос STMT_REMOVE: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = R"(
|
||||||
|
SELECT sha256 FROM files;
|
||||||
|
)";
|
||||||
|
|
||||||
|
if(sqlite3_prepare_v2(DB, sql, -1, &STMT_ALL_HASH, nullptr) != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить запрос STMT_ALL_HASH: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = R"(
|
||||||
|
SELECT SUM(size) FROM files;
|
||||||
|
)";
|
||||||
|
|
||||||
|
if(sqlite3_prepare_v2(DB, sql, -1, &STMT_SUM, nullptr) != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить запрос STMT_SUM: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = R"(
|
||||||
|
SELECT sha256
|
||||||
|
FROM files
|
||||||
|
WHERE last_used < ?
|
||||||
|
ORDER BY last_used ASC, size ASC
|
||||||
|
LIMIT (
|
||||||
|
SELECT COUNT(*) FROM (
|
||||||
|
SELECT SUM(size) OVER (ORDER BY last_used ASC, size ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total
|
||||||
|
FROM files
|
||||||
|
WHERE last_used < ?
|
||||||
|
ORDER BY last_used ASC, size ASC
|
||||||
|
) sub
|
||||||
|
WHERE running_total <= ?
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
|
||||||
|
if(sqlite3_prepare_v2(DB, sql, -1, &STMT_TO_FREE, nullptr) != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить запрос STMT_TO_FREE: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = R"(
|
||||||
|
SELECT COUNT(*) FROM files;
|
||||||
|
)";
|
||||||
|
|
||||||
|
if(sqlite3_prepare_v2(DB, sql, -1, &STMT_COUNT, nullptr) != SQLITE_OK) {
|
||||||
|
MAKE_ERROR("Не удалось подготовить запрос STMT_COUNT: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ResourceCacheHandler() {
|
||||||
|
for(sqlite3_stmt* stmt : {STMT_INSERT, STMT_UPDATE_TIME, STMT_REMOVE, STMT_ALL_HASH, STMT_SUM, STMT_TO_FREE, STMT_COUNT})
|
||||||
|
if(stmt)
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
|
||||||
|
if(DB)
|
||||||
|
sqlite3_close(DB);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceCacheHandler(const ResourceCacheHandler&) = delete;
|
||||||
|
ResourceCacheHandler(ResourceCacheHandler&&) = delete;
|
||||||
|
ResourceCacheHandler& operator=(const ResourceCacheHandler&) = delete;
|
||||||
|
ResourceCacheHandler& operator=(ResourceCacheHandler&&) = delete;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Выдаёт размер занимаемый всем хранимым кешем
|
||||||
|
*/
|
||||||
|
size_t getCacheSize() {
|
||||||
|
if(Size == -1) {
|
||||||
|
if(sqlite3_step(STMT_SUM) != SQLITE_ROW) {
|
||||||
|
sqlite3_reset(STMT_SUM);
|
||||||
|
MAKE_ERROR("Не удалось выполнить подготовленный запрос STMT_SUM: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = sqlite3_column_int(STMT_SUM, 0);
|
||||||
|
sqlite3_reset(STMT_SUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: добавить ограничения на количество файлов
|
||||||
|
|
||||||
|
/*
|
||||||
|
Создаёт линейный массив в котором подряд указаны все хэш суммы в бинарном виде и возвращает их количество
|
||||||
|
*/
|
||||||
|
std::pair<std::string, size_t> getAllHash() {
|
||||||
|
if(sqlite3_step(STMT_COUNT) != SQLITE_ROW) {
|
||||||
|
sqlite3_reset(STMT_COUNT);
|
||||||
|
MAKE_ERROR("Не удалось выполнить подготовленный запрос STMT_COUNT: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count = sqlite3_column_int(STMT_COUNT, 0);
|
||||||
|
sqlite3_reset(STMT_COUNT);
|
||||||
|
|
||||||
|
std::string out;
|
||||||
|
out.reserve(32*count);
|
||||||
|
|
||||||
|
int errc;
|
||||||
|
size_t readed = 0;
|
||||||
|
while(true) {
|
||||||
|
errc = sqlite3_step(STMT_ALL_HASH);
|
||||||
|
if(errc == SQLITE_DONE)
|
||||||
|
break;
|
||||||
|
else if(errc != SQLITE_ROW) {
|
||||||
|
sqlite3_reset(STMT_ALL_HASH);
|
||||||
|
MAKE_ERROR("Не удалось выполнить подготовленный запрос STMT_ALL_HASH: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *hash = (const char*) sqlite3_column_blob(STMT_ALL_HASH, 0);
|
||||||
|
readed++;
|
||||||
|
out += std::string_view(hash, hash+32);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(STMT_ALL_HASH);
|
||||||
|
return {out, readed};
|
||||||
|
}
|
||||||
|
|
||||||
|
using HASH = std::array<uint8_t, 32>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Обновляет время использования кеша
|
||||||
|
*/
|
||||||
|
void updateTimeFor(HASH hash) {
|
||||||
|
sqlite3_bind_blob(STMT_UPDATE_TIME, 0, (const void*) hash.data(), 32, SQLITE_STATIC);
|
||||||
|
sqlite3_bind_int(STMT_UPDATE_TIME, 1, time(nullptr));
|
||||||
|
if(sqlite3_step(STMT_UPDATE_TIME) != SQLITE_OK) {
|
||||||
|
sqlite3_reset(STMT_UPDATE_TIME);
|
||||||
|
MAKE_ERROR("Не удалось выполнить подготовленный запрос STMT_UPDATE_TIME: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(STMT_UPDATE_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Добавляет запись
|
||||||
|
*/
|
||||||
|
void insert(HASH hash, size_t size) {
|
||||||
|
assert(size < (size_t(1) << 31)-1 && size > 0);
|
||||||
|
|
||||||
|
sqlite3_bind_blob(STMT_INSERT, 0, (const void*) hash.data(), 32, SQLITE_STATIC);
|
||||||
|
sqlite3_bind_int(STMT_INSERT, 1, (int) size);
|
||||||
|
sqlite3_bind_int(STMT_INSERT, 2, time(nullptr));
|
||||||
|
if(sqlite3_step(STMT_INSERT) != SQLITE_OK) {
|
||||||
|
sqlite3_reset(STMT_INSERT);
|
||||||
|
MAKE_ERROR("Не удалось выполнить подготовленный запрос STMT_INSERT: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(STMT_INSERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Выдаёт хэши на удаление по размеру в сумме больше bytesToFree. В приоритете старые, потом мелкие
|
||||||
|
*/
|
||||||
|
std::vector<HASH> findExcessHashes(size_t bytesToFree, int timeBefore = time(nullptr)-604800) {
|
||||||
|
sqlite3_bind_int(STMT_TO_FREE, 0, timeBefore);
|
||||||
|
sqlite3_bind_int(STMT_TO_FREE, 1, timeBefore);
|
||||||
|
sqlite3_bind_int(STMT_TO_FREE, 2, (int) bytesToFree);
|
||||||
|
|
||||||
|
std::vector<HASH> out;
|
||||||
|
while(true) {
|
||||||
|
int errc = sqlite3_step(STMT_TO_FREE);
|
||||||
|
if(errc == SQLITE_DONE)
|
||||||
|
break;
|
||||||
|
else if(errc != SQLITE_ROW) {
|
||||||
|
sqlite3_reset(STMT_TO_FREE);
|
||||||
|
MAKE_ERROR("Не удалось выполнить подготовленный запрос STMT_TO_FREE: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *hash = (const uint8_t*) sqlite3_column_blob(STMT_TO_FREE, 0);
|
||||||
|
HASH obj;
|
||||||
|
for(int iter = 0; iter < 32; iter++)
|
||||||
|
obj[iter] = hash[iter];
|
||||||
|
|
||||||
|
out.push_back(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(STMT_TO_FREE);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Удаление записи
|
||||||
|
*/
|
||||||
|
void remove(HASH hash) {
|
||||||
|
sqlite3_bind_blob(STMT_REMOVE, 0, (const void*) hash.data(), 32, SQLITE_STATIC);
|
||||||
|
if(sqlite3_step(STMT_REMOVE) != SQLITE_OK) {
|
||||||
|
sqlite3_reset(STMT_REMOVE);
|
||||||
|
MAKE_ERROR("Не удалось выполнить подготовленный запрос STMT_REMOVE: " << sqlite3_errmsg(DB));
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_reset(STMT_REMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string hashToString(HASH hash) {
|
||||||
|
std::string text;
|
||||||
|
text.reserve(64);
|
||||||
|
|
||||||
|
for(int iter = 0; iter < 32; iter++) {
|
||||||
|
int val = hash[31-iter] & 0xf;
|
||||||
|
if(val > 9)
|
||||||
|
text += 'a'+val-10;
|
||||||
|
else
|
||||||
|
text += '0'+val;
|
||||||
|
|
||||||
|
val = (hash[31-iter] >> 4) & 0xf;
|
||||||
|
if(val > 9)
|
||||||
|
text += 'a'+val-10;
|
||||||
|
else
|
||||||
|
text += '0'+val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hexCharToInt(char c) {
|
||||||
|
if (c >= '0' && c <= '9') return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||||
|
throw std::invalid_argument("Invalid hexadecimal character");
|
||||||
|
}
|
||||||
|
|
||||||
|
static HASH stringToHash(const std::string_view view) {
|
||||||
|
if (view.size() != 64)
|
||||||
|
throw std::invalid_argument("Hex string must be exactly 64 characters long");
|
||||||
|
|
||||||
|
HASH hash;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 32; ++i) {
|
||||||
|
size_t offset = 62 - i * 2;
|
||||||
|
int high = hexCharToInt(view[offset]);
|
||||||
|
int low = hexCharToInt(view[offset + 1]);
|
||||||
|
hash[i] = (high << 4) | low;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "World.hpp"
|
#include "World.hpp"
|
||||||
|
|
||||||
#include "SaveBackend.hpp"
|
#include "SaveBackend.hpp"
|
||||||
|
#include "boost/asio/ip/address.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|||||||
15
Src/main.cpp
15
Src/main.cpp
@@ -2,8 +2,17 @@
|
|||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <Client/Vulkan/Vulkan.hpp>
|
#include <Client/Vulkan/Vulkan.hpp>
|
||||||
|
|
||||||
|
#include <Client/ResourceCache.hpp>
|
||||||
|
|
||||||
namespace LV {
|
namespace LV {
|
||||||
|
|
||||||
|
/*
|
||||||
|
База ресурсов на стороне клиента
|
||||||
|
Протокол получения ресурсов, удаления, потом -> регулировки размера
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
using namespace TOS;
|
using namespace TOS;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@@ -25,5 +34,9 @@ int main() {
|
|||||||
TOS::Logger::addLogFile(".*", TOS::EnumLogType::All, "log.raw");
|
TOS::Logger::addLogFile(".*", TOS::EnumLogType::All, "log.raw");
|
||||||
|
|
||||||
std::cout << "Hello world!" << std::endl;
|
std::cout << "Hello world!" << std::endl;
|
||||||
return LV::main();
|
//return LV::main();
|
||||||
|
|
||||||
|
LV::Client::ResourceCacheHandler handler("cache");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user