1 // This file is part of Desktop App Toolkit,
2 // a set of libraries for developing nice desktop applications.
3 //
4 // For license and copyright information please follow this link:
5 // https://github.com/desktop-app/legal/blob/master/LEGAL
6 //
7 #include "storage/cache/storage_cache_binlog_reader.h"
8
9 namespace Storage {
10 namespace Cache {
11 namespace details {
12
BinlogWrapper(File & binlog,const Settings & settings,int64 till)13 BinlogWrapper::BinlogWrapper(
14 File &binlog,
15 const Settings &settings,
16 int64 till)
17 : _binlog(binlog)
18 , _settings(settings)
19 , _till(till ? till : _binlog.size())
20 , _data(_settings.readBlockSize)
21 , _full(_data) {
22 }
23
finished() const24 bool BinlogWrapper::finished() const {
25 return _finished;
26 }
27
failed() const28 bool BinlogWrapper::failed() const {
29 return _failed;
30 }
31
ReadHeader(File & binlog,const Settings & settings)32 std::optional<BasicHeader> BinlogWrapper::ReadHeader(
33 File &binlog,
34 const Settings &settings) {
35 auto result = BasicHeader();
36 if (binlog.offset() != 0) {
37 return {};
38 } else if (binlog.read(bytes::object_as_span(&result)) != sizeof(result)) {
39 return {};
40 } else if (result.getFormat() != Format::Format_0) {
41 return {};
42 } else if (settings.trackEstimatedTime
43 != !!(result.flags & result.kTrackEstimatedTime)) {
44 return {};
45 }
46 return result;
47 }
48
readPart()49 bool BinlogWrapper::readPart() {
50 if (_finished) {
51 return false;
52 }
53 const auto no = [&] {
54 finish();
55 return false;
56 };
57 const auto offset = _binlog.offset();
58 const auto left = (_till - offset);
59 if (!left) {
60 return no();
61 }
62
63 if (!_part.empty() && _full.data() != _part.data()) {
64 bytes::move(_full, _part);
65 _part = _full.subspan(0, _part.size());
66 }
67 const auto amount = std::min(
68 left,
69 int64(_full.size() - _part.size()));
70 Assert(amount > 0);
71 const auto readBytes = _binlog.read(
72 _full.subspan(_part.size(), amount));
73 if (!readBytes) {
74 return no();
75 }
76 _part = _full.subspan(0, _part.size() + readBytes);
77 return true;
78 }
79
readRecord(ReadRecordSize readRecordSize)80 bytes::const_span BinlogWrapper::readRecord(ReadRecordSize readRecordSize) {
81 if (_finished) {
82 return {};
83 }
84 const auto size = readRecordSize(*this, _part);
85 if (size == kRecordSizeUnknown || size > _part.size()) {
86 return {};
87 } else if (size == kRecordSizeInvalid) {
88 finish();
89 _finished = _failed = true;
90 return {};
91 }
92 Assert(size >= 0);
93 const auto result = _part.subspan(0, size);
94 _part = _part.subspan(size);
95 return result;
96 }
97
finish(size_type rollback)98 void BinlogWrapper::finish(size_type rollback) {
99 Expects(rollback >= 0);
100
101 if (rollback > 0) {
102 _failed = true;
103 }
104 rollback += _part.size();
105 _binlog.seek(_binlog.offset() - rollback);
106 }
107
108 } // namespace details
109 } // namespace Cache
110 } // namespace Storage
111