1
0
mirror of https://github.com/danog/ton.git synced 2024-12-02 17:38:33 +01:00
ton/crypto/block/Binlog.h
2019-09-07 14:33:36 +04:00

158 lines
4.4 KiB
C++

/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "td/utils/Status.h"
#include "td/utils/port/FileFd.h"
namespace block {
/*
*
* BINLOG (BUFFERS) -- move to separate file
*
*/
class BinlogBuffer;
class BinlogCallback {
public:
virtual ~BinlogCallback() = default;
virtual td::Status init_new_binlog(BinlogBuffer& bb) = 0;
virtual int replay_log_event(BinlogBuffer& bb, const unsigned* ptr, std::size_t len, unsigned long long pos) = 0;
};
class BinlogBuffer {
static constexpr std::size_t max_event_size = 0xfffc;
std::unique_ptr<BinlogCallback> cb;
std::size_t max_size;
std::size_t need_more_bytes;
unsigned char *start, *rptr, *cptr, *wptr, *eptr, *end;
unsigned long long log_rpos, log_cpos, log_wpos;
std::string binlog_name;
td::FileFd fd;
bool replica;
bool writing;
bool dirty;
bool created;
bool ok;
td::Result<int> read_file();
td::Result<long long> replay_binlog(bool allow_partial);
unsigned char* try_alloc_log_event(std::size_t size);
int replay_pending(bool allow_partial = false);
void replay_range(unsigned char* ptr, unsigned long long pos_start, unsigned long long pos_end);
td::Status set_fd(td::FileFd fd);
public:
struct LevAllocError {
std::size_t size;
explicit LevAllocError(std::size_t _size) : size(_size) {
}
};
struct InterpretError {
std::string msg;
explicit InterpretError(std::string _msg) : msg(_msg) {
}
};
struct BinlogError {
std::string msg;
explicit BinlogError(std::string _msg) : msg(_msg) {
}
};
BinlogBuffer(std::unique_ptr<BinlogCallback> _cb, std::size_t _max_size = (1 << 24), td::FileFd fd = {});
BinlogBuffer(const BinlogBuffer&) = delete;
BinlogBuffer& operator=(const BinlogBuffer&) = delete;
BinlogBuffer(BinlogBuffer&&) = delete;
BinlogBuffer& operator=(BinlogBuffer&&) = delete;
~BinlogBuffer();
td::Status set_binlog(std::string _binlog_name, int mode = 0);
unsigned char* alloc_log_event(std::size_t size);
unsigned char* alloc_log_event_force(std::size_t size);
bool flush(int mode = 0);
td::Result<bool> try_flush(int mode);
unsigned long long get_rpos() const {
return log_rpos;
}
//
class NewBinlogEvent {
protected:
BinlogBuffer& bb;
unsigned long long pos;
unsigned size;
int status;
public:
NewBinlogEvent(BinlogBuffer& _bb, unsigned long long _pos, unsigned _size)
: bb(_bb), pos(_pos), size(_size), status(4) {
}
~NewBinlogEvent();
unsigned long long get_log_pos() const {
return pos;
}
void commit();
void commit_later() {
if (status & 4) {
status = 5;
}
}
void rollback();
void rollback_later() {
if (status & 4) {
status = 6;
}
};
};
template <typename T>
class NewEvent : public NewBinlogEvent {
T* ptr;
protected:
friend class BinlogBuffer;
NewEvent(BinlogBuffer& _bb, unsigned long long _pos, unsigned _size, T* _ptr)
: NewBinlogEvent(_bb, _pos, _size), ptr(_ptr) {
}
public:
T* operator->() const {
return ptr;
}
T& operator*() const {
return *ptr;
}
void commit() {
NewBinlogEvent::commit();
ptr = nullptr;
}
void rollback() {
NewBinlogEvent::rollback();
ptr = nullptr;
}
};
template <typename T, typename... Args>
NewEvent<T> alloc(Args... args) {
unsigned long long pos = log_wpos;
return NewEvent<T>(*this, pos, sizeof(T), new (alloc_log_event_force(sizeof(T))) T(args...));
}
protected:
friend class NewBinlogEvent;
bool commit_range(unsigned long long pos_start, unsigned long long pos_end);
bool rollback_range(unsigned long long pos_start, unsigned long long pos_end);
};
} // namespace block