Skip to content

Commit 35ec227

Browse files
committed
handle the case of concurrent appends to a file
1 parent 9778eee commit 35ec227

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

src/File.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,13 @@ namespace simgrid::fsmod {
8383
int File::write_init_checks(sg_size_t num_bytes) {
8484
static int sequence_number = -1;
8585
int my_sequence_number;
86+
8687
if (access_mode_ != "w" && access_mode_ != "a")
8788
throw std::invalid_argument("Invalid access mode. Cannot write in 'r' mode'");
8889

90+
if (access_mode_ == "a" && current_position_ < metadata_->get_future_size())
91+
current_position_ = metadata_->get_future_size();
92+
8993
//TODO: Would be good to move some of the code below to FileMetadata, but that requires
9094
// that FileMetadata know the partition....
9195

test/one_disk_storage_test.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
#include <gtest/gtest.h>
77
#include <iostream>
88

9-
#include <simgrid/s4u/Engine.hpp>
9+
#include <simgrid/s4u/ActivitySet.hpp>
1010
#include <simgrid/s4u/Actor.hpp>
11+
#include <simgrid/s4u/Engine.hpp>
1112

1213
#include "fsmod/PathUtil.hpp"
1314
#include "fsmod/FileSystem.hpp"
@@ -161,6 +162,35 @@ TEST_F(OneDiskStorageTest, SingleAsyncWrite) {
161162
});
162163
}
163164

165+
TEST_F(OneDiskStorageTest, DoubleAsyncAppend) {
166+
DO_TEST_WITH_FORK([this]() {
167+
xbt_log_control_set("root.thresh:info");
168+
this->setup_platform();
169+
sg4::Actor::create("TestActor", host_, [this]() {
170+
std::shared_ptr<sgfs::File> file;
171+
sg4::ActivitySet pending_writes;
172+
XBT_INFO("Create an empty file at /dev/a/foo.txt");
173+
ASSERT_NO_THROW(fs_->create_file("/dev/a/foo.txt", "0B"));
174+
XBT_INFO("Open File '/dev/a/foo.txt' in append mode");
175+
ASSERT_NO_THROW(file = fs_->open("/dev/a/foo.txt", "a"));
176+
XBT_INFO("Asynchronously write 2MB at /dev/a/foo.txt");
177+
ASSERT_NO_THROW(pending_writes.push(file->write_async("2MB")));
178+
XBT_INFO("Sleep for .1 second");
179+
ASSERT_NO_THROW(sg4::this_actor::sleep_for(0.1));
180+
XBT_INFO("Asynchronously write another 2MB at /dev/a/foo.txt");
181+
ASSERT_NO_THROW(pending_writes.push(file->write_async("2MB")));
182+
XBT_INFO("Wait for completion of both write operations");
183+
ASSERT_NO_THROW(pending_writes.wait_all());
184+
XBT_INFO("Close the file");
185+
ASSERT_NO_THROW(fs_->close(file));
186+
XBT_INFO("Check the file size, should be 4MB");
187+
ASSERT_EQ(fs_->file_size("/dev/a/foo.txt"), 4*1000*1000);
188+
});
189+
// Run the simulation
190+
ASSERT_NO_THROW(sg4::Engine::get_instance()->run());
191+
});
192+
}
193+
164194
TEST_F(OneDiskStorageTest, SingleAppendWrite) {
165195
DO_TEST_WITH_FORK([this]() {
166196
this->setup_platform();

0 commit comments

Comments
 (0)