Skip to content

Commit a116092

Browse files
committed
Fix XPRESS compression and enable in CI (#13649)
Summary: Somehow this was previously not being tested in our Windows CI jobs so was accidentally broken in #13540 This fix will need to be backported to 10.3. Pull Request resolved: #13649 Test Plan: CI Reviewed By: hx235 Differential Revision: D75655418 Pulled By: pdillinger fbshipit-source-id: a56bb213270904a1b7a13b905c2cc1919116df1c
1 parent f90d89e commit a116092

File tree

5 files changed

+78
-3
lines changed

5 files changed

+78
-3
lines changed

.github/actions/windows-build-steps/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ runs:
3838
$env:Path = $env:JAVA_HOME + ";" + $env:Path
3939
mkdir build
4040
cd build
41-
& cmake -G "$Env:CMAKE_GENERATOR" -DCMAKE_BUILD_TYPE=Debug -DOPTDBG=1 -DPORTABLE="$Env:CMAKE_PORTABLE" -DSNAPPY=1 -DJNI=1 ..
41+
& cmake -G "$Env:CMAKE_GENERATOR" -DCMAKE_BUILD_TYPE=Debug -DOPTDBG=1 -DPORTABLE="$Env:CMAKE_PORTABLE" -DSNAPPY=1 -DXPRESS=1 -DJNI=1 ..
4242
if(!$?) { Exit $LASTEXITCODE }
4343
cd ..
4444
echo "Building with VS version: $Env:CMAKE_GENERATOR"

port/win/xpress_win.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,69 @@ char* Decompress(const char* input_data, size_t input_length,
202202
return outputBuffer.release();
203203
}
204204

205+
int64_t GetDecompressedSize(const char* input_data, size_t input_length) {
206+
assert(input_data != nullptr);
207+
208+
if (input_length == 0) {
209+
return 0;
210+
}
211+
212+
COMPRESS_ALLOCATION_ROUTINES* allocRoutinesPtr = nullptr;
213+
214+
DECOMPRESSOR_HANDLE decompressor = NULL;
215+
216+
BOOL success =
217+
CreateDecompressor(COMPRESS_ALGORITHM_XPRESS, // Compression Algorithm
218+
allocRoutinesPtr, // Optional allocation routine
219+
&decompressor); // Handle
220+
221+
if (!success) {
222+
#ifdef _DEBUG
223+
std::cerr << "XPRESS: Failed to create Decompressor LastError "
224+
<< GetLastError() << std::endl;
225+
#endif
226+
return -1;
227+
}
228+
229+
std::unique_ptr<void, decltype(CloseDecompressorFun)> decompressorGuard(
230+
decompressor, CloseDecompressorFun);
231+
232+
SIZE_T decompressedBufferSize = 0;
233+
234+
success = ::Decompress(decompressor, // Compressor Handle
235+
const_cast<char*>(input_data), // Compressed data
236+
input_length, // Compressed data size
237+
NULL, // Buffer set to NULL
238+
0, // Buffer size set to 0
239+
&decompressedBufferSize); // Decompressed Data size
240+
241+
assert(!success);
242+
auto lastError = GetLastError();
243+
244+
if (lastError != ERROR_INSUFFICIENT_BUFFER) {
245+
#ifdef _DEBUG
246+
std::cerr
247+
<< "XPRESS: Failed to estimate decompressed buffer size LastError "
248+
<< lastError << std::endl;
249+
#endif
250+
return -1;
251+
}
252+
253+
assert(decompressedBufferSize > 0);
254+
return static_cast<int64_t>(decompressedBufferSize);
255+
}
256+
205257
int64_t DecompressToBuffer(const char* input, size_t input_length, char* output,
206258
size_t output_length) {
207259
assert(input != nullptr);
208260
assert(output != nullptr);
209261

262+
if (input_length == 0) {
263+
return 0;
264+
}
265+
266+
COMPRESS_ALLOCATION_ROUTINES* allocRoutinesPtr = nullptr;
267+
210268
DECOMPRESSOR_HANDLE decompressor = NULL;
211269

212270
BOOL success =

port/win/xpress_win.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ bool Compress(const char* input, size_t length, std::string* output);
2222
char* Decompress(const char* input_data, size_t input_length,
2323
size_t* uncompressed_size);
2424

25+
int64_t GetDecompressedSize(const char* input, size_t input_length);
26+
2527
int64_t DecompressToBuffer(const char* input, size_t input_length, char* output,
2628
size_t output_length);
2729

util/compression.cc

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ class BuiltinDecompressorV2 : public Decompressor {
590590
Status ExtractUncompressedSize(Args& args) override {
591591
assert(args.compression_type != kNoCompression);
592592
if (args.compression_type == kSnappyCompression) {
593-
// Exception to encoding of uncompressed size
593+
// 1st exception to encoding of uncompressed size
594594
#ifdef SNAPPY
595595
size_t uncompressed_length = 0;
596596
if (!snappy::GetUncompressedLength(args.compressed_data.data(),
@@ -603,6 +603,20 @@ class BuiltinDecompressorV2 : public Decompressor {
603603
#else
604604
return Status::NotSupported("Snappy not supported in this build");
605605
#endif
606+
} else if (args.compression_type == kXpressCompression) {
607+
// 2nd exception to encoding of uncompressed size
608+
#ifdef XPRESS
609+
int64_t result = port::xpress::GetDecompressedSize(
610+
args.compressed_data.data(), args.compressed_data.size());
611+
if (result < 0) {
612+
return Status::Corruption("Error reading XPRESS compressed length");
613+
}
614+
args.uncompressed_size = static_cast<size_t>(result);
615+
return Status::OK();
616+
#else
617+
return Status::NotSupported("XPRESS not supported in this build");
618+
#endif
619+
606620
} else {
607621
// Extract encoded uncompressed size
608622
return Decompressor::ExtractUncompressedSize(args);

util/compression.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,8 @@ inline std::string CompressionOptionsToString(
12601260
// block. Also, decompressed sizes for LZ4 are encoded in platform-dependent
12611261
// way.
12621262
// 2 -- Zlib, BZip2 and LZ4 encode decompressed size as Varint32 just before the
1263-
// start of compressed block. Snappy format is the same as version 1.
1263+
// start of compressed block. Snappy and XPRESS instead extract the decompressed
1264+
// size from the compressed block itself, same as version 1.
12641265

12651266
inline bool Snappy_Compress(const CompressionInfo& /*info*/, const char* input,
12661267
size_t length, ::std::string* output) {

0 commit comments

Comments
 (0)