BmnRoot
26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Toggle main menu visibility
Loading...
Searching...
No Matches
BmnFileReaderZStd.cxx
Go to the documentation of this file.
1
// headers from this target
2
#include "BmnFileReaderZStd.h"
3
4
#include "BmnDefinitions.h"
5
// std:: headers
6
#include <cassert>
7
#include <filesystem>
8
// FairLogger headers
9
#include <fairlogger/Logger.h>
10
// the main Zstd header
11
#ifdef BMNCOMPRESSION_WITH_ZSTD
12
#include <zstd.h>
13
#else
14
// If we build without the library, it would be find to use #pragma on the entire object, without push
15
// and pop, but it's nothing too important for us here - just for simplicity I'm going with this def
16
DISABLE_UNUSED_PARAM_WARNING
17
#endif
// BMNCOMPRESSION_WITH_ZSTD
18
19
// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
20
// ================== BmnFileReaderZStd public methods ==================
21
// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
22
23
// ========== BmnIFileReaderInterface ==========
24
25
BmnFileReaderZStd::BmnFileReaderZStd
(
const
std::string& fileName)
26
:
BmnIFileReader
(
BmnFileType
::
ZStd
, fileName)
27
,
fZstdStream
(nullptr)
28
,
fArchiveReadManager
(*this)
29
,
fNumberOfReadBytes
(0ull)
30
,
fLastReadReturnValue
(0ull)
31
{
32
#ifdef BMNCOMPRESSION_WITH_ZSTD
33
// Keeping it hidden so ZStd would be PRIVATE in CMake
34
static_assert
(ZSTD_VERSION_MAJOR >= 1 && ZSTD_VERSION_MINOR > 2,
35
"You are trying to use an old version of ZStd - in that version `ZSTD_DStream` was not the same as "
36
"`ZSTD_DCtx_s`!"
);
37
#endif
// BMNCOMPRESSION_WITH_ZSTD
38
}
39
40
BmnFileReaderZStd::BmnFileReaderZStd
(std::string&& fileName)
41
:
BmnIFileReader
(
BmnFileType
::
ZStd
,
std
::move(fileName))
42
,
fZstdStream
(nullptr)
43
,
fArchiveReadManager
(*this)
44
,
fNumberOfReadBytes
(0ull)
45
,
fLastReadReturnValue
(0ull)
46
{}
47
48
BmnFileReaderZStd::BmnFileReaderZStd
(
const
std::filesystem::path& filePath)
49
:
BmnIFileReader
(
BmnFileType
::
ZStd
, filePath)
50
,
fZstdStream
(nullptr)
51
,
fArchiveReadManager
(*this)
52
,
fNumberOfReadBytes
(0ull)
53
,
fLastReadReturnValue
(0ull)
54
{}
55
56
BmnFileReaderZStd::BmnFileReaderZStd
(std::filesystem::path&& filePath)
57
:
BmnIFileReader
(
BmnFileType
::
ZStd
,
std
::move(filePath))
58
,
fZstdStream
(nullptr)
59
,
fArchiveReadManager
(*this)
60
,
fNumberOfReadBytes
(0ull)
61
,
fLastReadReturnValue
(0ull)
62
{}
63
64
BmnFileReaderZStd::~BmnFileReaderZStd
()
65
{
66
BmnFileReaderZStd::Close
();
67
}
68
69
void
BmnFileReaderZStd::Open
(
const
BmnBinaryFileProcessingOptions
processingFlags)
70
{
71
#ifdef BMNCOMPRESSION_WITH_ZSTD
72
/*
73
While we actually don't need so many comments and checks here, we are still performing them just to ensure
74
one doesn't make an accidental mistake - it might be easier to catch it
75
*/
76
if
(
fZstdStream
) {
77
LOG(error) <<
"ZStd stream is already valid! The purpose of the BMN ZStd classes is to compress/decompress "
78
"huge files - if you however\n"
79
"really need to support compressing/decompressing many small files (frames), please let us know "
80
"and we will allow it along\n"
81
"with dictionaries (preferred for small files)\n"
;
82
return
;
83
}
84
if
(!
PerformStandardChecksBeforeOpening
(processingFlags))
85
return
;
86
fArchiveReadManager
.Open(
fFilePath
, std::ios::in | std::ios::binary);
87
fZstdStream
= ZSTD_createDStream();
88
#else
89
throw
std::runtime_error{
"Trying to use ZSTD while BMN is not compiled with it!"
};
90
#endif
// BMNCOMPRESSION_WITH_ZSTD
91
}
92
93
void
BmnFileReaderZStd::Close
() noexcept
94
{
95
#ifdef BMNCOMPRESSION_WITH_ZSTD
96
if
(!
fZstdStream
)
97
return
;
98
assert(
fArchiveReadManager
.IsOpen());
99
fLastReadReturnValue
= ZSTD_freeDStream(
fZstdStream
);
100
if
(ZSTD_isError(
fLastReadReturnValue
)) {
101
LOG(fatal) <<
"Failed to free ZStd stream - possible huge memory leak! Failure reason: "
102
<< ZSTD_getErrorName(
fLastReadReturnValue
) <<
'\n'
;
103
std::terminate();
104
}
105
fZstdStream
=
nullptr
;
106
fArchiveReadManager
.Close();
107
fNumberOfReadBytes
= 0ull;
108
fLastReadReturnValue
= 0ull;
109
#endif
// BMNCOMPRESSION_WITH_ZSTD
110
}
111
112
int64_t
BmnFileReaderZStd::Read
(
void
* dataToFill,
const
int64_t sizeToFill)
113
{
114
#ifdef BMNCOMPRESSION_WITH_ZSTD
115
if
(ZSTD_isError(
fLastReadReturnValue
))
116
return
0ll;
117
return
fArchiveReadManager
.Read(dataToFill, sizeToFill);
118
#else
119
throw
std::runtime_error{
"Trying to use ZSTD while BMN is not compiled with it!"
};
120
#endif
// BMNCOMPRESSION_WITH_ZSTD
121
}
122
123
int64_t
BmnFileReaderZStd::Tell
() const noexcept
124
{
125
return
fNumberOfReadBytes
+
fArchiveReadManager
.GetCurrentOutputBufferPosition()
126
-
fArchiveReadManager
.GetTotalOutputBufferFilledSize();
127
}
128
129
void
BmnFileReaderZStd::Seek
(int64_t value)
130
{
131
#ifdef BMNCOMPRESSION_WITH_ZSTD
132
if
(value < 0ll || (
size_t
)value ==
fNumberOfReadBytes
)
133
return
;
134
if
(ZSTD_isError(
fLastReadReturnValue
)) {
135
LOG(error) <<
"Before calling `BmnFileReaderZStd::Seek` ensure to clear bad flags!\n"
;
136
return
;
137
}
138
if
(!
fZstdStream
) {
139
LOG(error) <<
"Before calling `BmnFileReaderZStd::Seek` ensure to open the stream!\n"
;
140
return
;
141
}
142
if
(!
fArchiveReadManager
.IsOpen()) {
143
LOG(error) <<
"Reading file missing while calling `BmnFileReaderZStd::Seek`\n"
;
144
return
;
145
}
146
if
((
size_t
)value < (
fNumberOfReadBytes
-
fArchiveReadManager
.GetTotalOutputBufferFilledSize())) {
147
Close
();
148
Open
(
BmnBinaryFileProcessingOptions::ReadBinary
);
149
}
150
// in theory I could check IsOpen again for unexpected errors, but....
151
fArchiveReadManager
.MoveToDecompressingLocation(value);
152
#else
153
throw
std::runtime_error{
"Trying to use ZSTD while BMN is not compiled with it!"
};
154
#endif
// BMNCOMPRESSION_WITH_ZSTD
155
}
156
157
bool
BmnFileReaderZStd::IsGood
() const noexcept
158
{
159
#ifdef BMNCOMPRESSION_WITH_ZSTD
160
return
fZstdStream
&& !ZSTD_isError(
fLastReadReturnValue
) &&
fArchiveReadManager
.IsGood();
161
#else
162
return
false
;
163
#endif
// BMNCOMPRESSION_WITH_ZSTD
164
}
165
166
bool
BmnFileReaderZStd::IsEOF
() const noexcept
167
{
168
return
fArchiveReadManager
.IsEOF();
169
}
170
171
void
BmnFileReaderZStd::ClearStateFlags
()
172
{
173
// I don't like this method much
174
fLastReadReturnValue
= 0ull;
175
fArchiveReadManager
.Clear();
176
}
177
178
bool
BmnFileReaderZStd::IsOpen
() const noexcept
179
{
180
return
fArchiveReadManager
.IsOpen() &&
fZstdStream
;
181
}
182
183
// ========== BmnIArchiveLib Interface ==========
184
185
BmnFileStreamResults
BmnFileReaderZStd::Uncompress
(
const
void
* source,
186
const
size_t
sourceTotalSize,
187
size_t
& numberOfReadBytes,
188
void
* output,
189
const
size_t
outputTotalSize,
190
size_t
& numberOfSetOutputBytes)
191
{
192
if
(!
fZstdStream
)
193
return
BmnFileStreamResults::FileNotOpen
;
194
#ifdef BMNCOMPRESSION_WITH_ZSTD
195
if
(ZSTD_isError(
fLastReadReturnValue
))
196
return
BmnFileStreamResults::TryingToReadBadStream
;
197
ZSTD_outBuffer outBuffer{output, outputTotalSize, 0ull};
198
ZSTD_inBuffer inBuffer{source, sourceTotalSize, 0ull};
199
fLastReadReturnValue
= ZSTD_decompressStream(
fZstdStream
, &outBuffer, &inBuffer);
200
if
(ZSTD_isError(
fLastReadReturnValue
))
201
return
BmnFileStreamResults::UnexpectedFail
;
202
numberOfReadBytes = inBuffer.pos;
203
numberOfSetOutputBytes = outBuffer.pos;
204
fNumberOfReadBytes
+= outBuffer.pos;
205
if
(
fLastReadReturnValue
== 0ull)
206
return
BmnFileStreamResults::ReachedEOF
;
207
return
BmnFileStreamResults::Success
;
208
#else
209
throw
std::runtime_error{
"Trying to use ZSTD while BMN is not compiled with it!"
};
210
#endif
// BMNCOMPRESSION_WITH_ZSTD
211
}
212
213
std::string
BmnFileReaderZStd::GetLastUncompressErrorDescription
() const noexcept
214
{
215
#ifdef BMNCOMPRESSION_WITH_ZSTD
216
std::string strToReturn{};
217
if
(ZSTD_isError(
fLastReadReturnValue
))
218
strToReturn = std::string{ZSTD_getErrorName(
fLastReadReturnValue
)};
219
return
strToReturn;
220
#else
221
return
std::string{
"BMN NOT BUILT WITH ZSTD"
};
222
#endif
// BMNCOMPRESSION_WITH_ZSTD
223
}
224
225
bool
BmnFileReaderZStd::JumpsAllowed
() const noexcept
226
{
227
return
false
;
228
}
229
230
void
BmnFileReaderZStd::JumpTo
(
size_t
)
231
{
232
/*
233
Most compression libraries (including this one), don't like (read allow) jumping over the files and random
234
reads. In Zstd, it would be possible to implement it, but only at the compression level. In other words, we
235
would need to write the data in independent blocks or something similar. As we don't know what kind of a
236
compressed file we are currently reading, we cannot rely on that and we must read all the data to get to the
237
needed location - which is also what we currently need in BMN. If for some reason one needs to take some
238
other approach and allow fast random access, inherit this class and override this method
239
*/
240
LOG(warning) <<
"Calling `BmnFileReaderZStd::JumpTo` while the type doesn't allow jumping!\n"
;
241
}
242
243
size_t
BmnFileReaderZStd::GetNumberOfDecompressedBytes
() const noexcept
244
{
245
return
fNumberOfReadBytes
;
246
}
247
248
bool
BmnFileReaderZStd::HasReachedTheEndOfStream
() const noexcept
249
{
250
#ifdef BMNCOMPRESSION_WITH_ZSTD
251
if
(ZSTD_isError(
fLastReadReturnValue
))
252
return
true
;
253
return
fLastReadReturnValue
== 0;
254
#else
255
return
true
;
256
#endif
// BMNCOMPRESSION_WITH_ZSTD
257
}
258
259
bool
BmnFileReaderZStd::IsStreamInGoodState
() const noexcept
260
{
261
#ifdef BMNCOMPRESSION_WITH_ZSTD
262
return
!ZSTD_isError(
fLastReadReturnValue
);
263
#else
264
return
false
;
265
#endif
// BMNCOMPRESSION_WITH_ZSTD
266
}
267
268
#ifndef BMNCOMPRESSION_WITH_ZSTD
269
RESTORE_UNUSED_PARAM_WARNING
270
#endif
// BMNCOMPRESSION_WITH_ZSTD
RESTORE_UNUSED_PARAM_WARNING
#define RESTORE_UNUSED_PARAM_WARNING
Definition
BmnDefinitions.h:23
DISABLE_UNUSED_PARAM_WARNING
#define DISABLE_UNUSED_PARAM_WARNING
Definition
BmnDefinitions.h:22
BmnFileReaderZStd::Seek
virtual void Seek(int64_t value) override
Definition
BmnFileReaderZStd.cxx:129
BmnFileReaderZStd::Uncompress
virtual BmnFileStreamResults Uncompress(const void *source, const size_t sourceTotalSize, size_t &numberOfReadBytes, void *output, const size_t outputTotalSize, size_t &numberOfSetOutputBytes) override
Definition
BmnFileReaderZStd.cxx:185
BmnFileReaderZStd::IsGood
virtual bool IsGood() const noexcept override
Definition
BmnFileReaderZStd.cxx:157
BmnFileReaderZStd::~BmnFileReaderZStd
virtual ~BmnFileReaderZStd() override
Definition
BmnFileReaderZStd.cxx:64
BmnFileReaderZStd::Close
virtual void Close() noexcept override
Definition
BmnFileReaderZStd.cxx:93
BmnFileReaderZStd::fArchiveReadManager
BmnReaderCacheManager< 32ull *1024ull, 64ull *1024ull > fArchiveReadManager
Definition
BmnFileReaderZStd.h:208
BmnFileReaderZStd::ClearStateFlags
virtual void ClearStateFlags() override
Definition
BmnFileReaderZStd.cxx:171
BmnFileReaderZStd::GetNumberOfDecompressedBytes
virtual size_t GetNumberOfDecompressedBytes() const noexcept override
Definition
BmnFileReaderZStd.cxx:243
BmnFileReaderZStd::fNumberOfReadBytes
size_t fNumberOfReadBytes
Definition
BmnFileReaderZStd.h:209
BmnFileReaderZStd::IsStreamInGoodState
virtual bool IsStreamInGoodState() const noexcept override
Definition
BmnFileReaderZStd.cxx:259
BmnFileReaderZStd::Tell
virtual int64_t Tell() const noexcept override
Definition
BmnFileReaderZStd.cxx:123
BmnFileReaderZStd::GetLastUncompressErrorDescription
virtual std::string GetLastUncompressErrorDescription() const noexcept override
Definition
BmnFileReaderZStd.cxx:213
BmnFileReaderZStd::JumpTo
virtual void JumpTo(size_t) override
Definition
BmnFileReaderZStd.cxx:230
BmnFileReaderZStd::HasReachedTheEndOfStream
virtual bool HasReachedTheEndOfStream() const noexcept override
Definition
BmnFileReaderZStd.cxx:248
BmnFileReaderZStd::fLastReadReturnValue
size_t fLastReadReturnValue
Definition
BmnFileReaderZStd.h:210
BmnFileReaderZStd::Read
virtual int64_t Read(void *dataToFill, const int64_t sizeToFill) override
Definition
BmnFileReaderZStd.cxx:112
BmnFileReaderZStd::BmnFileReaderZStd
BmnFileReaderZStd(const std::string &fileName="")
Definition
BmnFileReaderZStd.cxx:25
BmnFileReaderZStd::IsOpen
virtual bool IsOpen() const noexcept override
Definition
BmnFileReaderZStd.cxx:178
BmnFileReaderZStd::fZstdStream
ZSTD_DCtx_s * fZstdStream
Definition
BmnFileReaderZStd.h:207
BmnFileReaderZStd::IsEOF
virtual bool IsEOF() const noexcept override
Definition
BmnFileReaderZStd.cxx:166
BmnFileReaderZStd::Open
virtual void Open(const BmnBinaryFileProcessingOptions processingFlags=BmnBinaryFileProcessingOptions::ReadBinary) override
Definition
BmnFileReaderZStd.cxx:69
BmnFileReaderZStd::JumpsAllowed
virtual bool JumpsAllowed() const noexcept override
Definition
BmnFileReaderZStd.cxx:225
BmnIFileReader::BmnIFileReader
BmnIFileReader(const BmnFileType fileType, const std::string &fileName="")
Definition
BmnIFileReader.cxx:8
BmnIFileReader::fFilePath
std::filesystem::path fFilePath
Definition
BmnIFileReader.h:199
BmnIFileReader::PerformStandardChecksBeforeOpening
bool PerformStandardChecksBeforeOpening(const BmnBinaryFileProcessingOptions processingFlags)
Definition
BmnIFileReader.cxx:72
BmnFileStreamResults
BmnFileStreamResults
Definition
BmnFileProcessingFlags.h:70
BmnFileStreamResults::Success
@ Success
Definition
BmnFileProcessingFlags.h:72
BmnFileStreamResults::ReachedEOF
@ ReachedEOF
Definition
BmnFileProcessingFlags.h:74
BmnFileStreamResults::FileNotOpen
@ FileNotOpen
Definition
BmnFileProcessingFlags.h:80
BmnFileStreamResults::UnexpectedFail
@ UnexpectedFail
Definition
BmnFileProcessingFlags.h:82
BmnFileStreamResults::TryingToReadBadStream
@ TryingToReadBadStream
Definition
BmnFileProcessingFlags.h:78
BmnFileType
BmnFileType
Definition
BmnFileProcessingFlags.h:16
BmnFileType::ZStd
@ ZStd
Definition
BmnFileProcessingFlags.h:19
BmnBinaryFileProcessingOptions
BmnBinaryFileProcessingOptions
Definition
BmnFileProcessingFlags.h:95
BmnBinaryFileProcessingOptions::ReadBinary
@ ReadBinary
Definition
BmnFileProcessingFlags.h:103
std
Definition
json.hpp:4446
compression
sources
BmnFileReaderZStd.cxx
Generated on
for BmnRoot by
1.17.0