diff --git a/fdbclient/BackupContainerLocalDirectory.actor.cpp b/fdbclient/BackupContainerLocalDirectory.actor.cpp index 9fb47fa036..3c73025d20 100644 --- a/fdbclient/BackupContainerLocalDirectory.actor.cpp +++ b/fdbclient/BackupContainerLocalDirectory.actor.cpp @@ -31,15 +31,37 @@ namespace { class BackupFile : public IBackupFile, ReferenceCounted<BackupFile> { public: BackupFile(std::string fileName, Reference<IAsyncFile> file, std::string finalFullPath) - : IBackupFile(fileName), m_file(file), m_finalFullPath(finalFullPath), m_offset(0) {} + : IBackupFile(fileName), m_file(file), m_finalFullPath(finalFullPath), m_writeOffset(0) { + m_buffer.reserve(m_buffer.arena(), CLIENT_KNOBS->BACKUP_LOCAL_FILE_WRITE_BLOCK); + } Future<Void> append(const void* data, int len) { - Future<Void> r = m_file->write(data, len, m_offset); - m_offset += len; + m_buffer.append(m_buffer.arena(), (const uint8_t*)data, len); + + if (m_buffer.size() >= CLIENT_KNOBS->BACKUP_LOCAL_FILE_WRITE_BLOCK) { + return flush(CLIENT_KNOBS->BACKUP_LOCAL_FILE_WRITE_BLOCK); + } + + return Void(); + } + + Future<Void> flush(int size) { + ASSERT(size <= m_buffer.size()); + + // Keep a reference to the old buffer + Standalone<VectorRef<uint8_t>> old = m_buffer; + // Make a new buffer, initialized with the excess bytes over the block size from the old buffer + m_buffer = Standalone<VectorRef<uint8_t>>(old.slice(size, old.size())); + + // Write the old buffer to the underlying file and update the write offset + Future<Void> r = holdWhile(old, m_file->write(old.begin(), size, m_writeOffset)); + m_writeOffset += size; + return r; } ACTOR static Future<Void> finish_impl(Reference<BackupFile> f) { + wait(f->flush(f->m_buffer.size())); wait(f->m_file->truncate(f->size())); // Some IAsyncFile implementations extend in whole block sizes. wait(f->m_file->sync()); std::string name = f->m_file->getFilename(); @@ -48,17 +70,18 @@ public: return Void(); } - Future<Void> finish() { return finish_impl(Reference<BackupFile>::addRef(this)); } + int64_t size() const { return m_buffer.size() + m_writeOffset; } - int64_t size() const override { return m_offset; } + Future<Void> finish() { return finish_impl(Reference<BackupFile>::addRef(this)); } void addref() override { return ReferenceCounted<BackupFile>::addref(); } void delref() override { return ReferenceCounted<BackupFile>::delref(); } private: Reference<IAsyncFile> m_file; + Standalone<VectorRef<uint8_t>> m_buffer; + int64_t m_writeOffset; std::string m_finalFullPath; - int64_t m_offset; }; ACTOR static Future<BackupContainerFileSystem::FilesAndSizesT> listFiles_impl(std::string path, std::string m_path) {