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