/* This file is part of TON Blockchain Library. TON Blockchain Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. TON Blockchain Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with TON Blockchain Library. If not, see . Copyright 2017-2020 Telegram Systems LLP */ #pragma once #include "BinlogReaderInterface.h" #include "td/db/utils/FileSyncState.h" #include "td/db/utils/StreamInterface.h" #include "td/actor/actor.h" #include "td/utils/misc.h" #include "td/utils/port/FileFd.h" namespace td { class BinlogReaderInterface; class StreamToFileActor; namespace detail { class FlushHelperActor; } // namespace detail class Binlog { public: explicit Binlog(string path); Status replay_sync(BinlogReaderInterface& binlog_reader); void replay_async(std::shared_ptr binlog_reader, Promise promise); static void destroy(CSlice path); void destroy(); private: string path_; }; class BinlogWriter { public: BinlogWriter(std::string path); Status open(); template Status write_event(EventT&& event, BinlogReaderInterface* binlog_reader); Status lazy_flush(); Status flush(); Status sync(); Status close(); private: string path_; FileFd fd_; StreamReader buf_reader_; StreamWriter buf_writer_; }; class BinlogWriterAsync { public: BinlogWriterAsync(std::string path); ~BinlogWriterAsync(); Status open(); template Status write_event(EventT&& event, BinlogReaderInterface* binlog_reader); void close(Promise<> promise); void lazy_flush(); void flush(); void sync(Promise promise = {}); private: std::string path_; StreamWriter buf_writer_; actor::ActorId writer_actor_; actor::ActorOwn flush_helper_actor_; FileSyncState::Reader sync_state_reader_; }; template Status BinlogWriter::write_event(EventT&& event, BinlogReaderInterface* binlog_reader) { int64 need_size = -event.serialize({}); auto dest = buf_writer_.prepare_write_at_least(narrow_cast(need_size)).truncate(narrow_cast(need_size)); auto written = event.serialize(dest); CHECK(written == need_size); if (binlog_reader != nullptr) { TRY_RESULT(parsed, binlog_reader->parse(dest)); binlog_reader->flush(); CHECK(parsed == written); } buf_writer_.confirm_write(narrow_cast(written)); return lazy_flush(); } template Status BinlogWriterAsync::write_event(EventT&& event, BinlogReaderInterface* binlog_reader) { int64 need_size = -event.serialize({}); auto dest = buf_writer_.prepare_write_at_least(narrow_cast(need_size)).truncate(narrow_cast(need_size)); auto written = event.serialize(dest); CHECK(written == need_size); if (binlog_reader != nullptr) { TRY_RESULT(parsed, binlog_reader->parse(dest)); CHECK(parsed == written); } buf_writer_.confirm_write(narrow_cast(written)); lazy_flush(); return Status::OK(); } } // namespace td