Skip to content
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
54 changes: 54 additions & 0 deletions .github/workflows/vtpc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Test VT Page Cache

on:
push:
branches:
- main
pull_request:
paths:
- 'lab/vtpc/**'

jobs:
build:
strategy:
matrix:
cmake_build_type:
- Asan
- Release
runs-on: ubuntu-latest
container:
image: silkeh/clang:latest
defaults:
run:
working-directory: ./lab/vtpc
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Clang Format
run: |
find . -path ./build -prune -o \
\( -iname '*.c' -o -iname '*.h' -o -iname '*.cpp' -o -iname '*.hpp' \) \
-exec clang-format --style=file --dry-run --verbose {} \;

- name: Configure
run: cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_build_type }}

- name: Build
run: cmake --build build

- name: Clang Tidy
if: matrix.cmake_build_type == 'Release'
run: |
find . -path ./build -prune -o \
\( -iname '*.c' -o -iname '*.h' -o -iname '*.cpp' -o -iname '*.hpp' \) -exec \
clang-tidy -p ./build {} \;

- name: Test Basic
run: ./build/test/test_basic

- name: Test Sequential
run: ./build/test/test_seq

- name: Test Random
run: ./build/test/test_random
11 changes: 7 additions & 4 deletions .github/workflows/vtsh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ jobs:

- name: Clang Format
run: |
find . -path ./build -prune -o \( -iname '*.c' -o -iname '*.h' \) -exec \
clang-format --style=file --dry-run --verbose {} \;
find . -path ./build -prune -o \
\( -iname '*.c' -o -iname '*.h' -o -iname '*.cpp' -o -iname '*.hpp' \) \
-exec clang-format --style=file --dry-run --verbose {} \;

- name: Configure
run: cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_build_type }}
Expand All @@ -37,9 +38,11 @@ jobs:
run: cmake --build build

- name: Clang Tidy
if: matrix.cmake_build_type == 'Release'
run: |
find . -path ./build -prune -o \( -iname '*.c' -o -iname '*.h' \) -exec \
clang-tidy -p . {} \;
find . -path ./build -prune -o \
\( -iname '*.c' -o -iname '*.h' -o -iname '*.cpp' -o -iname '*.hpp' \) -exec \
clang-tidy -p ./build {} \;

- name: Test
working-directory: ./lab/vtsh/test
Expand Down
16 changes: 16 additions & 0 deletions lab/vtpc/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
BasedOnStyle: Google

AccessModifierOffset: -2

AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false

DerivePointerAlignment: false
BreakConstructorInitializers: BeforeComma
AlignAfterOpenBracket: BlockIndent

BinPackArguments: false
BinPackParameters: false

AlignArrayOfStructures: Right
22 changes: 22 additions & 0 deletions lab/vtpc/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Checks: |
-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
cert-*,
clang-analyzer-*,
concurrency-*,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-special-member-functions,
google-*,
hicpp-*,
-hicpp-special-member-functions,
misc-*,
modernize-*,
performance-*,
portability-*,
-portability-avoid-pragma-once,
readability-*
-readability-identifier-length
WarningsAsErrors: '*'
FormatStyle: file
8 changes: 8 additions & 0 deletions lab/vtpc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# CMake
build/

# Clangd
.cache/

# Python
__pycache__/
7 changes: 7 additions & 0 deletions lab/vtpc/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"clangd.arguments": [
"-compile-commands-dir=./build",
"-header-insertion=never",
],
"files.eol": "\n",
}
12 changes: 12 additions & 0 deletions lab/vtpc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.12)

project(
vtpc
VERSION 0.1
DESCRIPTION "VT Page Cache"
)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

add_subdirectory(lib)
add_subdirectory(test)
47 changes: 47 additions & 0 deletions lab/vtpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Базовый трек. Лабораторная работа 2

## Задание

Для оптимизации работы с блочными устройствами в ОС существует кэш страниц с данными, которыми мы производим операции чтения и записи на диск. Такой кэш позволяет избежать высоких задержек при повторном доступе к данным, так как операция будет выполнена с данными в RAM, а не на диске (вспомним пирамиду памяти).

В данной лабораторной работе необходимо реализовать блочный кэш в пространстве пользователя в виде динамической библиотеки. Политику вытеснения страниц и другие элементы задания необходимо получить у преподавателя.

При выполнении работы необходимо реализовать простой API для работы с файлами, предоставляющий пользователю следующие возможности:

1. Открытие файла по заданному пути файла, доступного для чтения. Процедура возвращает некоторый хэндл на файл. Пример: `int lab2_open(const char *path)`.

2. Закрытие файла по хэндлу. Пример: `int lab2_close(int fd)`.

3. Чтение данных из файла. Пример: `ssize_t lab2_read(int fd, void buf[.count], size_t count)`.

4. Запись данных в файл. Пример: `ssize_t lab2_write(int fd, const void buf[.count], size_t count)`.

5. Перестановка позиции указателя на данные файла. Достаточно поддержать только абсолютные координаты. Пример: `​​​​​​​off_t lab2_lseek(int fd, off_t offset, int whence)`.

6. Синхронизация данных из кэша с диском. Пример: `int lab2_fsync(int fd)`.

Операции с диском разработанного блочного кеша должны производиться в обход page cache ОС.

В рамках проверки работоспособности разработанного блочного кэша необходимо адаптировать указанную преподавателем программу-загрузчик из ЛР 1, добавив использование кэша. Запустите программу и убедитесь, что она корректно работает. Сравните производительность до и после.

## Ограничения

1. Программа (комплекс программ) должна быть реализован на языке C.

2. Если по выданному варианту задана политика вытеснения Optimal, то необходимо предоставить пользователю возможность подсказать page cache, когда будет совершен следующий доступ к данным. Это можно сделать либо добавив параметр в процедуры `read` и `write` (например, `ssize_t lab2_read(int fd, void buf[.count], size_t count, access_hint_t hint)`), либо добавив еще одну функцию в API (например, `int lab2_advice(int fd, off_t offset, access_hint_t hint)`). `access_hint_t` в данном случае – это абсолютное время или временной интервал, по которому разработанное API будет определять время последующего доступа к данным.

3. Запрещено использовать высокоуровневые абстракции над системными вызовами.

## Требования к отчету и защите

Отчет должен содержать:

1. титульный лист с указанием номера и названия ЛР, вашего ФИО, ФИО преподавателя практики, номера вашей группы, варианта ЛР;

2. текст задания в соответствии с вариантом;

3. краткий обзор кода;

4. данные о работе программы-нагрузчика до и после внедрения своего page cache;

5. заключение с анализом результатов и выводом.
11 changes: 11 additions & 0 deletions lab/vtpc/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_library(
vtpc
STATIC
vtpc.c
)

target_include_directories(
vtpc
PUBLIC
.
)
30 changes: 30 additions & 0 deletions lab/vtpc/lib/vtpc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "vtpc.h"

#include <fcntl.h>
#include <stddef.h>
#include <sys/types.h>
#include <unistd.h>

int vtpc_open(const char* path, int mode, int access) {
return open(path, mode, access);
}

int vtpc_close(int fd) {
return close(fd);
}

ssize_t vtpc_read(int fd, void* buf, size_t count) {
return read(fd, buf, count);
}

ssize_t vtpc_write(int fd, const void* buf, size_t count) {
return write(fd, buf, count);
}

off_t vtpc_lseek(int fd, off_t offset, int whence) {
return lseek(fd, offset, whence);
}

int vtpc_fsync(int fd) {
return fsync(fd);
}
10 changes: 10 additions & 0 deletions lab/vtpc/lib/vtpc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <sys/types.h>

int vtpc_open(const char* path, int mode, int access);
int vtpc_close(int fd);
ssize_t vtpc_read(int fd, void* buf, size_t count);
ssize_t vtpc_write(int fd, const void* buf, size_t count);
off_t vtpc_lseek(int fd, off_t offset, int whence);
int vtpc_fsync(int fd);
17 changes: 17 additions & 0 deletions lab/vtpc/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_subdirectory(lib)

add_executable(test_basic test_basic.cpp)
target_include_directories(test_basic PUBLIC .)
target_link_libraries(test_basic PRIVATE vt)

add_executable(test_seq test_seq.cpp)
target_include_directories(test_seq PUBLIC .)
target_link_libraries(test_seq PRIVATE vt)

add_executable(test_random test_random.cpp)
target_include_directories(test_random PUBLIC .)
target_link_libraries(test_random PRIVATE vt)
11 changes: 11 additions & 0 deletions lab/vtpc/test/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_library(
vt
STATIC
cmp_file.cpp
exception.cpp
file.cpp
log_file.cpp
)

target_include_directories(vt PUBLIC .)
target_link_libraries(vt PRIVATE vtpc)
82 changes: 82 additions & 0 deletions lab/vtpc/test/lib/cmp_file.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "cmp_file.hpp"

#include <sys/types.h>

#include <cstddef>
#include <cstring>
#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "exception.hpp"
#include "file.hpp"

namespace vt {

template <class A, class B>
void Compare(A lhs, B rhs) {
std::optional<vt::file_exception> lhs_ex;
std::optional<vt::file_exception> rhs_ex;

try {
lhs();
} catch (const vt::file_exception& e) {
lhs_ex = vt::file_exception(e.code()) << e.what();
}

try {
rhs();
} catch (const vt::file_exception& e) {
rhs_ex = vt::file_exception(e.code()) << e.what();
}

if (lhs_ex && !rhs_ex) {
throw vt::cmp_file_exception() << "(FAIL, OK): " << lhs_ex->what();
}
if (!lhs_ex && rhs_ex) {
throw vt::cmp_file_exception() << "(OK, FAIL): " << rhs_ex->what();
}
if (lhs_ex && rhs_ex && lhs_ex->code() != rhs_ex->code()) {
throw vt::cmp_file_exception()
<< "(FAIL, FAIL), but codes differ: " << lhs_ex->what() << ", "
<< rhs_ex->what();
}
if (lhs_ex && rhs_ex) {
const vt::file_exception& e = *lhs_ex;
throw vt::file_exception(e.code()) << e.what();
}
}

cmp_file::cmp_file(std::unique_ptr<file> lhs, std::unique_ptr<file> rhs)
: lhs_(std::move(lhs)), file_(std::move(rhs)) {
}

auto cmp_file::read(char* buffer, size_t count) -> void {
std::string lhs(count, ' ');
std::string rhs(count, ' ');
Compare(
[&] { lhs_->read(lhs.data(), count); },
[&] { file_->read(rhs.data(), count); }
);
if (lhs != rhs) {
throw vt::cmp_file_exception() << "'" << lhs << "' != '" << rhs << "'";
}
memcpy(buffer, lhs.data(), count);
}

auto cmp_file::write(const char* buffer, size_t count) -> void {
Compare(
[&] { lhs_->write(buffer, count); }, [&] { file_->write(buffer, count); }
);
}

auto cmp_file::seek(off_t offset) -> void {
Compare([&] { lhs_->seek(offset); }, [&] { file_->seek(offset); });
}

auto cmp_file::sync() -> void {
Compare([&] { lhs_->sync(); }, [this] { file_->sync(); });
}

} // namespace vt
33 changes: 33 additions & 0 deletions lab/vtpc/test/lib/cmp_file.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <sys/types.h>

#include <cstddef>
#include <memory>

#include "exception.hpp"
#include "file.hpp"

namespace vt {

class cmp_file_exception : public vt::exception {};

class cmp_file final : public file {
public:
using file::read;
using file::write;

cmp_file(std::unique_ptr<file> lhs, std::unique_ptr<file> rhs);
~cmp_file() override = default;

auto read(char* buffer, size_t count) -> void override;
auto write(const char* buffer, size_t count) -> void override;
auto seek(off_t offset) -> void override;
auto sync() -> void override;

private:
std::unique_ptr<file> lhs_;
std::unique_ptr<file> file_;
};

} // namespace vt
Loading