]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/port/win/xpress_win.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / port / win / xpress_win.cc
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
2// This source code is licensed under both the GPLv2 (found in the
3// COPYING file in the root directory) and Apache 2.0 License
4// (found in the LICENSE.Apache file in the root directory).
7c673cae
FG
5//
6// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7// Use of this source code is governed by a BSD-style license that can be
8// found in the LICENSE file. See the AUTHORS file for names of contributors.
9
20effc67
TL
10#if defined(OS_WIN)
11
7c673cae 12#include "port/win/xpress_win.h"
11fdf7f2 13#include <windows.h>
7c673cae
FG
14
15#include <cassert>
16#include <memory>
17#include <limits>
18#include <iostream>
19
20#ifdef XPRESS
21
7c673cae
FG
22// Put this under ifdef so windows systems w/o this
23// can still build
24#include <compressapi.h>
25
f67539c2 26namespace ROCKSDB_NAMESPACE {
7c673cae
FG
27namespace port {
28namespace xpress {
29
30// Helpers
31namespace {
32
33auto CloseCompressorFun = [](void* h) {
34 if (NULL != h) {
35 ::CloseCompressor(reinterpret_cast<COMPRESSOR_HANDLE>(h));
36 }
37};
38
39auto CloseDecompressorFun = [](void* h) {
40 if (NULL != h) {
41 ::CloseDecompressor(reinterpret_cast<DECOMPRESSOR_HANDLE>(h));
42 }
43};
7c673cae
FG
44}
45
46bool Compress(const char* input, size_t length, std::string* output) {
47
48 assert(input != nullptr);
49 assert(output != nullptr);
50
51 if (length == 0) {
52 output->clear();
53 return true;
54 }
55
56 COMPRESS_ALLOCATION_ROUTINES* allocRoutinesPtr = nullptr;
57
7c673cae
FG
58 COMPRESSOR_HANDLE compressor = NULL;
59
60 BOOL success = CreateCompressor(
61 COMPRESS_ALGORITHM_XPRESS, // Compression Algorithm
62 allocRoutinesPtr, // Optional allocation routine
63 &compressor); // Handle
64
65 if (!success) {
66#ifdef _DEBUG
67 std::cerr << "XPRESS: Failed to create Compressor LastError: " <<
11fdf7f2 68 GetLastError() << std::endl;
7c673cae
FG
69#endif
70 return false;
71 }
72
73 std::unique_ptr<void, decltype(CloseCompressorFun)>
11fdf7f2 74 compressorGuard(compressor, CloseCompressorFun);
7c673cae
FG
75
76 SIZE_T compressedBufferSize = 0;
77
11fdf7f2 78 // Query compressed buffer size.
7c673cae
FG
79 success = ::Compress(
80 compressor, // Compressor Handle
81 const_cast<char*>(input), // Input buffer
82 length, // Uncompressed data size
83 NULL, // Compressed Buffer
84 0, // Compressed Buffer size
85 &compressedBufferSize); // Compressed Data size
86
87 if (!success) {
88
89 auto lastError = GetLastError();
90
91 if (lastError != ERROR_INSUFFICIENT_BUFFER) {
92#ifdef _DEBUG
93 std::cerr <<
94 "XPRESS: Failed to estimate compressed buffer size LastError " <<
95 lastError << std::endl;
96#endif
11fdf7f2
TL
97 return false;
98 }
7c673cae
FG
99 }
100
101 assert(compressedBufferSize > 0);
102
103 std::string result;
104 result.resize(compressedBufferSize);
105
106 SIZE_T compressedDataSize = 0;
107
108 // Compress
109 success = ::Compress(
110 compressor, // Compressor Handle
111 const_cast<char*>(input), // Input buffer
112 length, // Uncompressed data size
113 &result[0], // Compressed Buffer
114 compressedBufferSize, // Compressed Buffer size
115 &compressedDataSize); // Compressed Data size
116
117 if (!success) {
118#ifdef _DEBUG
119 std::cerr << "XPRESS: Failed to compress LastError " <<
11fdf7f2 120 GetLastError() << std::endl;
7c673cae
FG
121#endif
122 return false;
123 }
124
125 result.resize(compressedDataSize);
126 output->swap(result);
127
128 return true;
129}
130
131char* Decompress(const char* input_data, size_t input_length,
20effc67 132 size_t* uncompressed_size) {
7c673cae 133 assert(input_data != nullptr);
20effc67 134 assert(uncompressed_size != nullptr);
7c673cae
FG
135
136 if (input_length == 0) {
137 return nullptr;
138 }
139
140 COMPRESS_ALLOCATION_ROUTINES* allocRoutinesPtr = nullptr;
141
7c673cae
FG
142 DECOMPRESSOR_HANDLE decompressor = NULL;
143
144 BOOL success = CreateDecompressor(
145 COMPRESS_ALGORITHM_XPRESS, // Compression Algorithm
146 allocRoutinesPtr, // Optional allocation routine
147 &decompressor); // Handle
148
149
150 if (!success) {
151#ifdef _DEBUG
152 std::cerr << "XPRESS: Failed to create Decompressor LastError "
11fdf7f2 153 << GetLastError() << std::endl;
7c673cae
FG
154#endif
155 return nullptr;
156 }
157
158 std::unique_ptr<void, decltype(CloseDecompressorFun)>
159 compressorGuard(decompressor, CloseDecompressorFun);
160
161 SIZE_T decompressedBufferSize = 0;
162
163 success = ::Decompress(
164 decompressor, // Compressor Handle
165 const_cast<char*>(input_data), // Compressed data
166 input_length, // Compressed data size
167 NULL, // Buffer set to NULL
168 0, // Buffer size set to 0
169 &decompressedBufferSize); // Decompressed Data size
170
171 if (!success) {
172
173 auto lastError = GetLastError();
174
175 if (lastError != ERROR_INSUFFICIENT_BUFFER) {
176#ifdef _DEBUG
177 std::cerr
11fdf7f2
TL
178 << "XPRESS: Failed to estimate decompressed buffer size LastError "
179 << lastError << std::endl;
7c673cae
FG
180#endif
181 return nullptr;
182 }
183 }
184
185 assert(decompressedBufferSize > 0);
186
7c673cae
FG
187 // The callers are deallocating using delete[]
188 // thus we must allocate with new[]
189 std::unique_ptr<char[]> outputBuffer(new char[decompressedBufferSize]);
190
191 SIZE_T decompressedDataSize = 0;
192
193 success = ::Decompress(
194 decompressor,
195 const_cast<char*>(input_data),
196 input_length,
197 outputBuffer.get(),
198 decompressedBufferSize,
199 &decompressedDataSize);
200
201 if (!success) {
202#ifdef _DEBUG
203 std::cerr <<
204 "XPRESS: Failed to decompress LastError " <<
205 GetLastError() << std::endl;
206#endif
207 return nullptr;
208 }
209
20effc67 210 *uncompressed_size = decompressedDataSize;
7c673cae
FG
211
212 // Return the raw buffer to the caller supporting the tradition
213 return outputBuffer.release();
214}
215}
216}
f67539c2 217} // namespace ROCKSDB_NAMESPACE
7c673cae
FG
218
219#endif
20effc67
TL
220
221#endif