Merge pull request #4418 from sfc-gh-mpilman/features/async-rename
Add async rename
This commit is contained in:
commit
02e575e49b
|
@ -107,6 +107,33 @@ public:
|
|||
return Void();
|
||||
}
|
||||
|
||||
ACTOR static Future<Void> renameFile(std::string from, std::string to) {
|
||||
state TaskPriority taskID = g_network->getCurrentTask();
|
||||
state Promise<Void> p;
|
||||
state eio_req* r = eio_rename(from.c_str(), to.c_str(), 0, eio_callback, &p);
|
||||
try {
|
||||
wait(p.getFuture());
|
||||
} catch (...) {
|
||||
g_network->setCurrentTask(taskID);
|
||||
eio_cancel(r);
|
||||
throw;
|
||||
}
|
||||
try {
|
||||
state int result = r->result;
|
||||
if(result == -1) {
|
||||
TraceEvent(SevError, "FileRenameError").detail("Errno", r->errorno);
|
||||
throw internal_error();
|
||||
} else {
|
||||
wait(delay(0, taskID));
|
||||
return Void();
|
||||
}
|
||||
} catch (Error& e) {
|
||||
state Error _e = e;
|
||||
wait(delay(0, taskID));
|
||||
throw _e;
|
||||
}
|
||||
}
|
||||
|
||||
ACTOR static Future<std::time_t> lastWriteTime( std::string filename ) {
|
||||
EIO_STRUCT_STAT statdata = wait(stat_impl(filename));
|
||||
return statdata.st_mtime;
|
||||
|
|
|
@ -128,6 +128,12 @@ public:
|
|||
|
||||
return result.getFuture();
|
||||
}
|
||||
|
||||
static Future<Void> renameFile(std::string const& from, std::string const& to) {
|
||||
::renameFile(from, to);
|
||||
return Void();
|
||||
}
|
||||
|
||||
virtual Future<Void> write( void const* data, int length, int64_t offset ) {
|
||||
/*
|
||||
FIXME
|
||||
|
|
|
@ -132,3 +132,55 @@ TEST_CASE("/fileio/incrementalDelete" ) {
|
|||
wait(IAsyncFileSystem::filesystem()->incrementalDeleteFile(filename, true));
|
||||
return Void();
|
||||
}
|
||||
|
||||
TEST_CASE("/fileio/rename") {
|
||||
// create a file
|
||||
state int64_t fileSize = 100e6;
|
||||
state std::string filename = "/tmp/__JUNK__." + deterministicRandom()->randomUniqueID().toString();
|
||||
state std::string renamedFile = "/tmp/__RENAMED_JUNK__." + deterministicRandom()->randomUniqueID().toString();
|
||||
state std::unique_ptr<char[]> data(new char[4096]);
|
||||
state std::unique_ptr<char[]> readData(new char[4096]);
|
||||
state Reference<IAsyncFile> f = wait(IAsyncFileSystem::filesystem()->open(
|
||||
filename, IAsyncFile::OPEN_ATOMIC_WRITE_AND_CREATE | IAsyncFile::OPEN_CREATE | IAsyncFile::OPEN_READWRITE,
|
||||
0644));
|
||||
;
|
||||
wait(f->sync());
|
||||
wait(f->truncate(fileSize));
|
||||
memset(data.get(), 0, 4096);
|
||||
// write a random string at the beginning of the file which we can verify after rename
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
data[i] = deterministicRandom()->randomAlphaNumeric();
|
||||
}
|
||||
// write first and block
|
||||
wait(f->write(data.get(), 4096, 0));
|
||||
wait(f->write(data.get(), 4096, fileSize - 4096));
|
||||
wait(f->sync());
|
||||
// close file
|
||||
f.clear();
|
||||
wait(IAsyncFileSystem::filesystem()->renameFile(filename, renamedFile));
|
||||
Reference<IAsyncFile> _f = wait(IAsyncFileSystem::filesystem()->open(renamedFile, IAsyncFile::OPEN_READONLY, 0));
|
||||
f = _f;
|
||||
|
||||
// verify rename happened
|
||||
bool renamedExists = false;
|
||||
auto bName = basename(renamedFile);
|
||||
auto files = platform::listFiles("/tmp/");
|
||||
for (const auto& file : files) {
|
||||
if (file == bName) {
|
||||
renamedExists = true;
|
||||
}
|
||||
ASSERT(file != filename);
|
||||
}
|
||||
ASSERT(renamedExists);
|
||||
|
||||
// verify magic string at beginning of file
|
||||
int length = wait(f->read(readData.get(), 4096, 0));
|
||||
ASSERT(length == 4096);
|
||||
ASSERT(memcmp(readData.get(), data.get(), 4096) == 0);
|
||||
// close the file
|
||||
f.clear();
|
||||
|
||||
// clean up
|
||||
wait(IAsyncFileSystem::filesystem()->deleteFile(renamedFile, true));
|
||||
return Void();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#ifndef FLOW_IASYNCFILE_H
|
||||
#define FLOW_IASYNCFILE_H
|
||||
#include <string>
|
||||
#pragma once
|
||||
|
||||
#include <ctime>
|
||||
|
@ -98,6 +99,9 @@ public:
|
|||
// Deletes the given file. If mustBeDurable, returns only when the file is guaranteed to be deleted even after a power failure.
|
||||
virtual Future< Void > deleteFile( std::string filename, bool mustBeDurable ) = 0;
|
||||
|
||||
// renames the file, doesn't sync the directory
|
||||
virtual Future<Void> renameFile(std::string const& from, std::string const& to) = 0;
|
||||
|
||||
// Unlinks a file and then deletes it slowly by truncating the file repeatedly.
|
||||
// If mustBeDurable, returns only when the file is guaranteed to be deleted even after a power failure.
|
||||
virtual Future<Void> incrementalDeleteFile( std::string filename, bool mustBeDurable );
|
||||
|
|
|
@ -115,6 +115,10 @@ Net2FileSystem::Net2FileSystem(double ioTimeout, std::string fileSystemPath)
|
|||
#endif
|
||||
}
|
||||
|
||||
Future<Void> Net2FileSystem::renameFile(const std::string &from, const std::string &to) {
|
||||
return Net2AsyncFile::renameFile(from, to);
|
||||
}
|
||||
|
||||
void Net2FileSystem::stop() {
|
||||
Net2AsyncFile::stop();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#ifndef FLOW_NET2FILESYSTEM_H
|
||||
#define FLOW_NET2FILESYSTEM_H
|
||||
#include <string>
|
||||
#pragma once
|
||||
|
||||
#include "fdbrpc/IAsyncFile.h"
|
||||
|
@ -27,13 +28,15 @@
|
|||
class Net2FileSystem : public IAsyncFileSystem {
|
||||
public:
|
||||
// Opens a file for asynchronous I/O
|
||||
virtual Future< Reference<class IAsyncFile> > open( std::string filename, int64_t flags, int64_t mode );
|
||||
Future< Reference<class IAsyncFile> > open( std::string filename, int64_t flags, int64_t mode ) override;
|
||||
|
||||
// Deletes the given file. If mustBeDurable, returns only when the file is guaranteed to be deleted even after a power failure.
|
||||
virtual Future< Void > deleteFile( std::string filename, bool mustBeDurable );
|
||||
Future< Void > deleteFile( std::string filename, bool mustBeDurable ) override;
|
||||
|
||||
Future<Void> renameFile(std::string const& from, std::string const& to) override;
|
||||
|
||||
// Returns the time of the last modification of the file.
|
||||
virtual Future< std::time_t > lastWriteTime( std::string filename );
|
||||
Future< std::time_t > lastWriteTime( std::string filename ) override;
|
||||
|
||||
//void init();
|
||||
static void stop();
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
*/
|
||||
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
|
||||
#include "fdbrpc/simulator.h"
|
||||
#include "flow/flow.h"
|
||||
#include "flow/IThreadPool.h"
|
||||
#include "flow/Util.h"
|
||||
#include "fdbrpc/IAsyncFile.h"
|
||||
|
@ -1847,6 +1849,17 @@ Future< Void > Sim2FileSystem::deleteFile( std::string filename, bool mustBeDura
|
|||
return Sim2::deleteFileImpl(&g_sim2, filename, mustBeDurable);
|
||||
}
|
||||
|
||||
ACTOR Future<Void> renameFileImpl(std::string from, std::string to) {
|
||||
wait(delay(0.5*deterministicRandom()->random01()));
|
||||
::renameFile(from, to);
|
||||
wait(delay(0.5*deterministicRandom()->random01()));
|
||||
return Void();
|
||||
}
|
||||
|
||||
Future<Void> Sim2FileSystem::renameFile(std::string const& from, std::string const& to) {
|
||||
return renameFileImpl(from, to);
|
||||
}
|
||||
|
||||
Future< std::time_t > Sim2FileSystem::lastWriteTime( std::string filename ) {
|
||||
// TODO: update this map upon file writes.
|
||||
static std::map<std::string, double> fileWrites;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#ifndef FLOW_SIMULATOR_H
|
||||
#define FLOW_SIMULATOR_H
|
||||
#include <string>
|
||||
#pragma once
|
||||
|
||||
#include "flow/flow.h"
|
||||
|
@ -361,12 +362,14 @@ extern Future<Void> waitUntilDiskReady(Reference<DiskParameters> parameters, int
|
|||
class Sim2FileSystem : public IAsyncFileSystem {
|
||||
public:
|
||||
// Opens a file for asynchronous I/O
|
||||
virtual Future< Reference<class IAsyncFile> > open( std::string filename, int64_t flags, int64_t mode );
|
||||
Future<Reference<class IAsyncFile>> open( std::string filename, int64_t flags, int64_t mode ) override;
|
||||
|
||||
// Deletes the given file. If mustBeDurable, returns only when the file is guaranteed to be deleted even after a power failure.
|
||||
virtual Future< Void > deleteFile( std::string filename, bool mustBeDurable );
|
||||
Future<Void> deleteFile(std::string filename, bool mustBeDurable) override;
|
||||
|
||||
virtual Future< std::time_t > lastWriteTime( std::string filename );
|
||||
Future<Void> renameFile(std::string const& from, std::string const& to) override;
|
||||
|
||||
Future< std::time_t > lastWriteTime( std::string filename ) override;
|
||||
|
||||
Sim2FileSystem() {}
|
||||
|
||||
|
|
Loading…
Reference in New Issue