Skip to content

Commit

Permalink
add OneRemoteDiskStorage and activate Failure tests
Browse files Browse the repository at this point in the history
  • Loading branch information
frs69wq committed Dec 13, 2024
1 parent c0eb47f commit 8ad8f01
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ set(SOURCE_FILES
src/Storage.cpp
src/JBODStorage.cpp
src/OneDiskStorage.cpp
src/OneRemoteDiskStorage.cpp
)

set(HEADER_FILES
Expand All @@ -55,6 +56,7 @@ set(HEADER_FILES
include/fsmod/PathUtil.hpp
include/fsmod/FileSystem.hpp
include/fsmod/OneDiskStorage.hpp
include/fsmod/OneRemoteDiskStorage.hpp
include/fsmod/Storage.hpp
)

Expand All @@ -81,6 +83,7 @@ if(GTEST_LIBRARY)
set(TEST_FILES
test/jbod_storage_test.cpp
test/one_disk_storage_test.cpp
test/one_remote_disk_storage_test.cpp
test/path_util_test.cpp
test/file_system_test.cpp
test/seek_test.cpp
Expand Down
1 change: 1 addition & 0 deletions include/fsmod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
#include <fsmod/Storage.hpp>
#include <fsmod/JBODStorage.hpp>
#include <fsmod/OneDiskStorage.hpp>
#include <fsmod/OneRemoteDiskStorage.hpp>

#endif //FSMOD_FSMOD_HPP
30 changes: 30 additions & 0 deletions include/fsmod/OneRemoteDiskStorage.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef FSMOD_ONEREMOTEDISKSTORAGE_HPP
#define FSMOD_ONEREMOTEDISKSTORAGE_HPP

/* Copyright (c) 2024. The FSMOD Team. All rights reserved. */

/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */

#include "Storage.hpp"

namespace simgrid::fsmod {

/**
* @brief A class that implements a one-disk storage
*/
class XBT_PUBLIC OneRemoteDiskStorage : public Storage {
public:
OneRemoteDiskStorage(const std::string &name, simgrid::s4u::Disk *disk);
~OneRemoteDiskStorage() override = default;
static std::shared_ptr<OneRemoteDiskStorage> create(const std::string &name, simgrid::s4u::Disk *disk);

protected:
s4u::IoPtr read_async(sg_size_t size) override;
void read(sg_size_t size) override;
s4u::IoPtr write_async(sg_size_t size) override;
void write(sg_size_t size) override;
};
} // namespace simgrid::fsmod

#endif //FSMOD_ONEREMOTEDISKSTORAGE_HPP
47 changes: 47 additions & 0 deletions src/OneRemoteDiskStorage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* Copyright (c) 2024. The FSMOD Team. All rights reserved. */

/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */

#include "fsmod/OneRemoteDiskStorage.hpp"
#include <simgrid/s4u/Actor.hpp>

namespace simgrid::fsmod {

/**
* @brief Create an instance of a remote one-disk storage
* @param name: the storage's name
* @param disk: the storage's disk
* @return a remote one-disk storage instance
*/
std::shared_ptr<OneRemoteDiskStorage> OneRemoteDiskStorage::create(const std::string& name, s4u::Disk* disk) {
return std::make_shared<OneRemoteDiskStorage>(name, disk);
}

OneRemoteDiskStorage::OneRemoteDiskStorage(const std::string& name, s4u::Disk* disk) : Storage(name) {
set_disk(disk);
}

s4u::IoPtr OneRemoteDiskStorage::read_async(sg_size_t size) {
auto source_host = get_controller_host();
if (source_host == nullptr)
source_host = this->get_first_disk()->get_host();
return s4u::Io::streamto_async(source_host, get_first_disk(), s4u::Host::current(), nullptr, size);
}

void OneRemoteDiskStorage::read(sg_size_t size) {
this->read_async(size)->wait();
}

s4u::IoPtr OneRemoteDiskStorage::write_async(sg_size_t size) {
auto destination_host = get_controller_host();
if (destination_host == nullptr)
destination_host= this->get_first_disk()->get_host();
return s4u::Io::streamto_async(s4u::Host::current(), nullptr, destination_host, get_first_disk(), size);
}

void OneRemoteDiskStorage::write(sg_size_t size) {
this->write_async(size)->wait();
}

}
6 changes: 3 additions & 3 deletions test/one_disk_storage_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,10 @@ TEST_F(OneDiskStorageTest, DiskFailure) {
XBT_INFO("Write 2MB at /dev/a/foo.txt");
ASSERT_NO_THROW(my_write = file->write_async("2MB"));
ASSERT_NO_THROW(sg4::this_actor::sleep_for(1));
//ASSERT_NO_THROW(disk_->turn_off());
ASSERT_NO_THROW(disk_->turn_off());
ASSERT_NO_THROW(sg4::this_actor::sleep_for(1));
//ASSERT_NO_THROW(disk_->turn_on());
ASSERT_NO_THROW(my_write->wait());
ASSERT_NO_THROW(disk_->turn_on());
ASSERT_THROW(my_write->wait(), simgrid::StorageFailureException);
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
});
Expand Down
243 changes: 243 additions & 0 deletions test/one_remote_disk_storage_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
/* Copyright (c) 2024. The FSMOD Team. All rights reserved. */

/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */

#include <gtest/gtest.h>
#include <iostream>

#include <simgrid/s4u/ActivitySet.hpp>
#include <simgrid/s4u/Actor.hpp>
#include <simgrid/s4u/Engine.hpp>

#include "fsmod/FileSystem.hpp"
#include "fsmod/OneRemoteDiskStorage.hpp"
#include "fsmod/FileSystemException.hpp"

#include "./test_util.hpp"

namespace sgfs=simgrid::fsmod;
namespace sg4=simgrid::s4u;

XBT_LOG_NEW_DEFAULT_CATEGORY(rods_io_test, "OneRemoteDiskStorage I/O Test");

class OneRemoteDiskStorageTest : public ::testing::Test {
public:
std::shared_ptr<sgfs::FileSystem> fs_;
sg4::Host * client_;
sg4::Host * server_;
sg4::Disk * disk_;

OneRemoteDiskStorageTest() = default;

void setup_platform() {
XBT_INFO("Creating a platform with one client host and a server host with one disk...");
auto *my_zone = sg4::create_full_zone("zone");
client_ = my_zone->create_host("client", "100Gf");
server_ = my_zone->create_host("server", "100Gf");
disk_ = server_->create_disk("disk_one", "2MBps", "1MBps");
const auto* link = my_zone->create_link("link", 1e9);
my_zone->add_route(client_, server_, {link});
my_zone->seal();

XBT_INFO("Creating a one-disk storage on the host's disk...");
auto rods = sgfs::OneRemoteDiskStorage::create("my_storage", disk_);
XBT_INFO("Creating a file system...");
fs_ = sgfs::FileSystem::create("my_fs");
XBT_INFO("Mounting a 100MB partition...");
fs_->mount_partition("/dev/a/", rods, "100MB");
}
};


TEST_F(OneRemoteDiskStorageTest, SingleRead) {
DO_TEST_WITH_FORK([this]() {
this->setup_platform();
sg4::Actor::create("TestActor", client_, [this]() {
std::shared_ptr<sgfs::File> file;
XBT_INFO("Create a 10kB file at /dev/a/foo.txt");
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "10kB"));
XBT_INFO("Open File '/dev/a/foo.txt'");
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "r"));
XBT_INFO("read 0B at /dev/a/foo.txt, which should return 0");
ASSERT_DOUBLE_EQ(file->read(0), 0);
XBT_INFO("read 100kB at /dev/a/foo.txt, which should return only 10kB");
ASSERT_DOUBLE_EQ(file->read("100kB"), 10000);
XBT_INFO("read 10kB at /dev/a/foo.txt, which should return O as we are at the end of the file");
ASSERT_DOUBLE_EQ(file->read("10kB"), 0);
XBT_INFO("Seek back to SEEK_SET and read 9kB at /dev/a/foo.txt");
ASSERT_NO_THROW(file->seek(SEEK_SET));
ASSERT_DOUBLE_EQ(file->read("9kB"), 9000);
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
});
// Run the simulation
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
});
}

TEST_F(OneRemoteDiskStorageTest, SingleAsyncRead) {
DO_TEST_WITH_FORK([this]() {
this->setup_platform();
sg4::Actor::create("TestActor", client_, [this]() {
std::shared_ptr<sgfs::File> file;
sg4::IoPtr my_read;
sg_size_t num_bytes_read = 0;
XBT_INFO("Create a 10MB file at /dev/a/foo.txt");
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "10MB"));
XBT_INFO("Open File '/dev/a/foo.txt'");
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "r"));
XBT_INFO("Asynchronously read 2MB at /dev/a/foo.txt");
ASSERT_NO_THROW(my_read = file->read_async("4MB"));
XBT_INFO("Sleep for 1 second");
ASSERT_NO_THROW(sg4::this_actor::sleep_for(1));
XBT_INFO("Sleep complete. Clock should be at 1s");
ASSERT_DOUBLE_EQ(sg4::Engine::get_clock(), 1.0);
XBT_INFO("Wait for read completion");
ASSERT_NO_THROW(my_read->wait());
XBT_INFO("Read complete. Clock should be at 2s");
ASSERT_DOUBLE_EQ(sg4::Engine::get_clock(), 2.0);
ASSERT_DOUBLE_EQ(sgfs::File::get_num_bytes_read(my_read), 4000000);
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
});
// Run the simulation
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
});
}

TEST_F(OneRemoteDiskStorageTest, SingleWrite) {
DO_TEST_WITH_FORK([this]() {
this->setup_platform();
sg4::Actor::create("TestActor", client_, [this]() {
std::shared_ptr<sgfs::File> file;
XBT_INFO("Create a 1MB file at /dev/a/foo.txt");
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "1MB"));
XBT_INFO("Check remaining space");
ASSERT_DOUBLE_EQ(fs_->partition_by_name("/dev/a")->get_free_space(), 99 * 1000 *1000);
XBT_INFO("Open File '/dev/a/foo.txt'");
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "w"));
XBT_INFO("Opening file in 'w' mode reset size to 0. Check remaining space");
ASSERT_DOUBLE_EQ(fs_->partition_by_name("/dev/a")->get_free_space(), 100 * 1000 *1000);
XBT_INFO("Write 0B at /dev/a/foo.txt, which should return 0");
ASSERT_DOUBLE_EQ(file->write(0), 0);
XBT_INFO("Write 200MB at /dev/a/foo.txt, which should not work");
ASSERT_THROW(file->write("200MB"), sgfs::NotEnoughSpaceException);
XBT_INFO("Write 2MB at /dev/a/foo.txt");
ASSERT_DOUBLE_EQ(file->write("2MB"), 2000000);
XBT_INFO("Check remaining space");
ASSERT_DOUBLE_EQ(fs_->partition_by_name("/dev/a")->get_free_space(), 98 * 1000 * 1000);
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
});
// Run the simulation
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
});
}

TEST_F(OneRemoteDiskStorageTest, SingleAsyncWrite) {
DO_TEST_WITH_FORK([this]() {
this->setup_platform();
sg4::Actor::create("TestActor", client_, [this]() {
std::shared_ptr<sgfs::File> file;
sg4::IoPtr my_write;
sg_size_t num_bytes_written = 0;
XBT_INFO("Create a 10MB file at /dev/a/foo.txt");
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "10MB"));
XBT_INFO("Open File '/dev/a/foo.txt'");
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "w"));
XBT_INFO("Asynchronously write 2MB at /dev/a/foo.txt");
ASSERT_NO_THROW(my_write = file->write_async("2MB"));
XBT_INFO("Sleep for 1 second");
ASSERT_NO_THROW(sg4::this_actor::sleep_for(1));
XBT_INFO("Sleep complete. Clock should be at 1s");
ASSERT_DOUBLE_EQ(sg4::Engine::get_clock(), 1.0);
XBT_INFO("Wait for write completion");
ASSERT_NO_THROW(my_write->wait());
XBT_INFO("Write complete. Clock should be at 2s");
ASSERT_DOUBLE_EQ(sg4::Engine::get_clock(), 2.0);
ASSERT_DOUBLE_EQ(file->get_num_bytes_written(my_write), 2000000);
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
});
// Run the simulation
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
});
}

TEST_F(OneRemoteDiskStorageTest, DoubleAsyncAppend) {
DO_TEST_WITH_FORK([this]() {
this->setup_platform();
sg4::Actor::create("TestActor", client_, [this]() {
std::shared_ptr<sgfs::File> file;
sg4::ActivitySet pending_writes;
XBT_INFO("Create an empty file at /dev/a/foo.txt");
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "0B"));
XBT_INFO("Open File '/dev/a/foo.txt' in append mode");
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "a"));
XBT_INFO("Asynchronously write 2MB at /dev/a/foo.txt");
ASSERT_NO_THROW(pending_writes.push(file->write_async("2MB")));
XBT_INFO("Sleep for .1 second");
ASSERT_NO_THROW(sg4::this_actor::sleep_for(0.1));
XBT_INFO("Asynchronously write another 2MB at /dev/a/foo.txt");
ASSERT_NO_THROW(pending_writes.push(file->write_async("2MB")));
XBT_INFO("Wait for completion of both write operations");
ASSERT_NO_THROW(pending_writes.wait_all());
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
XBT_INFO("Check the file size, should be 4MB");
ASSERT_EQ(fs_->file_size("/dev/a/foo.txt"), 4*1000*1000);
});
// Run the simulation
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
});
}

TEST_F(OneRemoteDiskStorageTest, SingleAppendWrite) {
DO_TEST_WITH_FORK([this]() {
this->setup_platform();
sg4::Actor::create("TestActor", client_, [this]() {
std::shared_ptr<sgfs::File> file;
sg4::IoPtr my_write;
sg_size_t num_bytes_written = 0;
XBT_INFO("Create a 10MB file at /dev/a/foo.txt");
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "10MB"));
XBT_INFO("Open File '/dev/a/foo.txt' in append mode ('a')");
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "a"));
XBT_INFO("Write 2MB at /dev/a/foo.txt");
ASSERT_NO_THROW(file->write("2MB"));
XBT_INFO("Check file size, it should still be 12MB");
ASSERT_DOUBLE_EQ(fs_->file_size("/dev/a/foo.txt"), 12*1000*1000);
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
});
// Run the simulation
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
});
}

TEST_F(OneRemoteDiskStorageTest, DiskFailure) {
DO_TEST_WITH_FORK([this]() {
this->setup_platform();
sg4::Actor::create("TestActor", client_, [this]() {
std::shared_ptr<sgfs::File> file;
sg4::IoPtr my_write;
sg_size_t num_bytes_written = 0;
XBT_INFO("Create a 10MB file at /dev/a/foo.txt");
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "10MB"));
XBT_INFO("Open File '/dev/a/foo.txt' in append mode ('a')");
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "a"));
XBT_INFO("Write 2MB at /dev/a/foo.txt");
ASSERT_NO_THROW(my_write = file->write_async("2MB"));
ASSERT_NO_THROW(sg4::this_actor::sleep_for(1));
ASSERT_NO_THROW(disk_->turn_off());
ASSERT_NO_THROW(sg4::this_actor::sleep_for(1));
ASSERT_NO_THROW(disk_->turn_on());
ASSERT_THROW(my_write->wait(), simgrid::StorageFailureException);
XBT_INFO("Close the file");
ASSERT_NO_THROW(file->close());
});
// Run the simulation
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
});
}

0 comments on commit 8ad8f01

Please sign in to comment.