Changeset View
Changeset View
Standalone View
Standalone View
src/flatfile.cpp
Show All 11 Lines | |||||
FlatFileSeq::FlatFileSeq(fs::path dir, const char *prefix, size_t chunk_size) | FlatFileSeq::FlatFileSeq(fs::path dir, const char *prefix, size_t chunk_size) | ||||
: m_dir(std::move(dir)), m_prefix(prefix), m_chunk_size(chunk_size) { | : m_dir(std::move(dir)), m_prefix(prefix), m_chunk_size(chunk_size) { | ||||
if (chunk_size == 0) { | if (chunk_size == 0) { | ||||
throw std::invalid_argument("chunk_size must be positive"); | throw std::invalid_argument("chunk_size must be positive"); | ||||
} | } | ||||
} | } | ||||
std::string CDiskBlockPos::ToString() const { | std::string FlatFilePos::ToString() const { | ||||
return strprintf("CDiskBlockPos(nFile=%i, nPos=%i)", nFile, nPos); | return strprintf("FlatFilePos(nFile=%i, nPos=%i)", nFile, nPos); | ||||
} | } | ||||
fs::path FlatFileSeq::FileName(const CDiskBlockPos &pos) const { | fs::path FlatFileSeq::FileName(const FlatFilePos &pos) const { | ||||
return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); | return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); | ||||
} | } | ||||
FILE *FlatFileSeq::Open(const CDiskBlockPos &pos, bool fReadOnly) { | FILE *FlatFileSeq::Open(const FlatFilePos &pos, bool fReadOnly) { | ||||
if (pos.IsNull()) return nullptr; | if (pos.IsNull()) return nullptr; | ||||
fs::path path = FileName(pos); | fs::path path = FileName(pos); | ||||
fs::create_directories(path.parent_path()); | fs::create_directories(path.parent_path()); | ||||
FILE *file = fsbridge::fopen(path, fReadOnly ? "rb" : "rb+"); | FILE *file = fsbridge::fopen(path, fReadOnly ? "rb" : "rb+"); | ||||
if (!file && !fReadOnly) { | if (!file && !fReadOnly) { | ||||
file = fsbridge::fopen(path, "wb+"); | file = fsbridge::fopen(path, "wb+"); | ||||
} | } | ||||
if (!file) { | if (!file) { | ||||
LogPrintf("Unable to open file %s\n", path.string()); | LogPrintf("Unable to open file %s\n", path.string()); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
if (pos.nPos) { | if (pos.nPos) { | ||||
if (fseek(file, pos.nPos, SEEK_SET)) { | if (fseek(file, pos.nPos, SEEK_SET)) { | ||||
LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, | LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, | ||||
path.string()); | path.string()); | ||||
fclose(file); | fclose(file); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
return file; | return file; | ||||
} | } | ||||
size_t FlatFileSeq::Allocate(const CDiskBlockPos &pos, size_t add_size, | size_t FlatFileSeq::Allocate(const FlatFilePos &pos, size_t add_size, | ||||
bool &out_of_space) { | bool &out_of_space) { | ||||
out_of_space = false; | out_of_space = false; | ||||
unsigned int n_old_chunks = (pos.nPos + m_chunk_size - 1) / m_chunk_size; | unsigned int n_old_chunks = (pos.nPos + m_chunk_size - 1) / m_chunk_size; | ||||
unsigned int n_new_chunks = | unsigned int n_new_chunks = | ||||
(pos.nPos + add_size + m_chunk_size - 1) / m_chunk_size; | (pos.nPos + add_size + m_chunk_size - 1) / m_chunk_size; | ||||
if (n_new_chunks > n_old_chunks) { | if (n_new_chunks > n_old_chunks) { | ||||
size_t old_size = pos.nPos; | size_t old_size = pos.nPos; | ||||
Show All 11 Lines | if (n_new_chunks > n_old_chunks) { | ||||
} | } | ||||
} else { | } else { | ||||
out_of_space = true; | out_of_space = true; | ||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
bool FlatFileSeq::Flush(const CDiskBlockPos &pos, bool finalize) { | bool FlatFileSeq::Flush(const FlatFilePos &pos, bool finalize) { | ||||
FILE *file = Open(CDiskBlockPos(pos.nFile, 0)); // Avoid fseek to nPos | FILE *file = Open(FlatFilePos(pos.nFile, 0)); // Avoid fseek to nPos | ||||
if (!file) { | if (!file) { | ||||
return error("%s: failed to open file %d", __func__, pos.nFile); | return error("%s: failed to open file %d", __func__, pos.nFile); | ||||
} | } | ||||
if (finalize && !TruncateFile(file, pos.nPos)) { | if (finalize && !TruncateFile(file, pos.nPos)) { | ||||
fclose(file); | fclose(file); | ||||
return error("%s: failed to truncate file %d", __func__, pos.nFile); | return error("%s: failed to truncate file %d", __func__, pos.nFile); | ||||
} | } | ||||
if (!FileCommit(file)) { | if (!FileCommit(file)) { | ||||
fclose(file); | fclose(file); | ||||
return error("%s: failed to commit file %d", __func__, pos.nFile); | return error("%s: failed to commit file %d", __func__, pos.nFile); | ||||
} | } | ||||
fclose(file); | fclose(file); | ||||
return true; | return true; | ||||
} | } |