Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add storage version info #1436

Merged
merged 1 commit into from
Apr 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.11)

project(Kuzu VERSION 0.0.3.1 LANGUAGES CXX)
project(Kuzu VERSION 0.0.3 LANGUAGES CXX)

find_package(Threads REQUIRED)

Expand Down Expand Up @@ -78,6 +78,7 @@ function(add_kuzu_test TEST_NAME)
endfunction()

add_definitions(-DKUZU_ROOT_DIRECTORY="${PROJECT_SOURCE_DIR}")
add_definitions(-DKUZU_STORAGE_VERSION="${CMAKE_PROJECT_VERSION}")

set(ARROW_INSTALL ${CMAKE_CURRENT_SOURCE_DIR}/external/build/arrow/install)
find_library(ARROW_DEPS_PATH arrow_bundled_dependencies HINTS ${ARROW_INSTALL}/lib ${ARROW_INSTALL}/lib64)
Expand Down
37 changes: 37 additions & 0 deletions src/catalog/catalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ void CatalogContent::saveToFile(const std::string& directory, DBFileType dbFileT
auto catalogPath = StorageUtils::getCatalogFilePath(directory, dbFileType);
auto fileInfo = FileUtils::openFile(catalogPath, O_WRONLY | O_CREAT);
uint64_t offset = 0;
writeMagicBytes(fileInfo.get(), offset);
offset = SerDeser::serializeValue<uint64_t>(
StorageVersionInfo::getStorageVersion(), fileInfo.get(), offset);
offset = SerDeser::serializeValue<uint64_t>(nodeTableSchemas.size(), fileInfo.get(), offset);
offset = SerDeser::serializeValue<uint64_t>(relTableSchemas.size(), fileInfo.get(), offset);
for (auto& nodeTableSchema : nodeTableSchemas) {
Expand All @@ -316,6 +319,10 @@ void CatalogContent::readFromFile(const std::string& directory, DBFileType dbFil
logger->debug("Reading from {}.", catalogPath);
auto fileInfo = FileUtils::openFile(catalogPath, O_RDONLY);
uint64_t offset = 0;
validateMagicBytes(fileInfo.get(), offset);
storage::storage_version_t savedStorageVersion;
offset = SerDeser::deserializeValue<uint64_t>(savedStorageVersion, fileInfo.get(), offset);
validateStorageVersion(savedStorageVersion);
uint64_t numNodeTables, numRelTables;
offset = SerDeser::deserializeValue<uint64_t>(numNodeTables, fileInfo.get(), offset);
offset = SerDeser::deserializeValue<uint64_t>(numRelTables, fileInfo.get(), offset);
Expand All @@ -342,6 +349,36 @@ void CatalogContent::readFromFile(const std::string& directory, DBFileType dbFil
SerDeser::deserializeValue<table_id_t>(nextTableID, fileInfo.get(), offset);
}

void CatalogContent::validateStorageVersion(storage_version_t savedStorageVersion) const {
auto storageVersion = StorageVersionInfo::getStorageVersion();
if (savedStorageVersion != storageVersion) {
throw common::RuntimeException(StringUtils::string_format(
"Trying to read a database file with a different version. "
"Database file version: {}, Current build storage version: {}",
savedStorageVersion, storageVersion));
}
}

void CatalogContent::validateMagicBytes(FileInfo* fileInfo, offset_t& offset) const {
auto numMagicBytes = strlen(StorageVersionInfo::MAGIC_BYTES);
uint8_t magicBytes[4];
for (auto i = 0u; i < numMagicBytes; i++) {
offset = SerDeser::deserializeValue<uint8_t>(magicBytes[i], fileInfo, offset);
}
if (memcmp(magicBytes, StorageVersionInfo::MAGIC_BYTES, numMagicBytes) != 0) {
throw common::RuntimeException(
"This is not a valid Kuzu database directory for the current version of Kuzu.");
}
}

void CatalogContent::writeMagicBytes(FileInfo* fileInfo, offset_t& offset) const {
auto numMagicBytes = strlen(StorageVersionInfo::MAGIC_BYTES);
for (auto i = 0u; i < numMagicBytes; i++) {
offset =
SerDeser::serializeValue<uint8_t>(StorageVersionInfo::MAGIC_BYTES[i], fileInfo, offset);
}
}

Catalog::Catalog() : wal{nullptr} {
catalogContentForReadOnlyTrx = std::make_unique<CatalogContent>();
builtInVectorOperations = std::make_unique<function::BuiltInVectorOperations>();
Expand Down
7 changes: 7 additions & 0 deletions src/include/catalog/catalog.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "common/utils.h"
#include "function/aggregate/built_in_aggregate_functions.h"
#include "function/built_in_vector_operations.h"
#include "storage/storage_info.h"
#include "storage/wal/wal.h"

namespace spdlog {
Expand Down Expand Up @@ -133,6 +134,12 @@ class CatalogContent {
private:
inline common::table_id_t assignNextTableID() { return nextTableID++; }

void validateStorageVersion(storage::storage_version_t savedStorageVersion) const;

void validateMagicBytes(common::FileInfo* fileInfo, common::offset_t& offset) const;

void writeMagicBytes(common::FileInfo* fileInfo, common::offset_t& offset) const;

private:
std::shared_ptr<spdlog::logger> logger;
std::unordered_map<common::table_id_t, std::unique_ptr<NodeTableSchema>> nodeTableSchemas;
Expand Down
31 changes: 31 additions & 0 deletions src/include/storage/storage_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "exception"
#include <string>

#include "common/utils.h"

namespace kuzu {
namespace storage {

using storage_version_t = uint64_t;

struct StorageVersionInfo {
static std::unordered_map<std::string, storage_version_t> getStorageVersionInfo() {
return {{"0.0.3", 1}};
}

static storage_version_t getStorageVersion() {
auto storageVersionInfo = getStorageVersionInfo();
if (!storageVersionInfo.contains(KUZU_STORAGE_VERSION)) {
throw common::RuntimeException(common::StringUtils::string_format(
"Invalid storage version name: {}", KUZU_STORAGE_VERSION));
}
return storageVersionInfo.at(KUZU_STORAGE_VERSION);
}

static constexpr const char* MAGIC_BYTES = "KUZU";
};

} // namespace storage
} // namespace kuzu