We implement CompressFile() manually using zlib APIs rather than forking out to '/bin/gzip' since fork() can be expensive on processes that use a large amount of memory. During the time of the fork, other threads could end up blocked. Implementing it using the zlib stream APIs isn't too much code and is less likely to be problematic.
| 248 | // blocked. Implementing it using the zlib stream APIs isn't too much code |
| 249 | // and is less likely to be problematic. |
| 250 | Status RollingLog::CompressFile(const std::string& path) const { |
| 251 | unique_ptr<SequentialFile> in_file; |
| 252 | SequentialFileOptions opts; |
| 253 | opts.is_sensitive = false; |
| 254 | RETURN_NOT_OK_PREPEND(env_->NewSequentialFile(opts, path, &in_file), |
| 255 | "Unable to open input file to compress"); |
| 256 | |
| 257 | string gz_path = path + ".gz"; |
| 258 | gzFile gzf = gzopen(gz_path.c_str(), "w"); |
| 259 | if (!gzf) { |
| 260 | return Status::IOError("Unable to open gzip stream"); |
| 261 | } |
| 262 | |
| 263 | ScopedGzipCloser closer(gzf); |
| 264 | |
| 265 | // Loop reading data from the input file and writing to the gzip stream. |
| 266 | uint8_t buf[32 * 1024]; |
| 267 | while (true) { |
| 268 | Slice result(buf, arraysize(buf)); |
| 269 | RETURN_NOT_OK_PREPEND(in_file->Read(&result), |
| 270 | "Unable to read from gzip input"); |
| 271 | if (result.size() == 0) { |
| 272 | break; |
| 273 | } |
| 274 | int n = gzwrite(gzf, result.data(), result.size()); |
| 275 | if (n == 0) { |
| 276 | int errnum; |
| 277 | return Status::IOError("Unable to write to gzip output", |
| 278 | gzerror(gzf, &errnum)); |
| 279 | } |
| 280 | } |
| 281 | closer.Cancel(); |
| 282 | RETURN_NOT_OK_PREPEND(GzClose(gzf), |
| 283 | "Unable to close gzip output"); |
| 284 | |
| 285 | WARN_NOT_OK(env_->DeleteFile(path), |
| 286 | "Unable to delete gzip input file after compression"); |
| 287 | return Status::OK(); |
| 288 | } |
| 289 | |
| 290 | } // namespace kudu |
nothing calls this directly
no test coverage detected