Path: blob/master/src/hotspot/share/services/heapDumperCompression.hpp
64440 views
/*1* Copyright (c) 2020 SAP SE. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_SERVICES_HEAPDUMPERCOMPRESSION_HPP25#define SHARE_SERVICES_HEAPDUMPERCOMPRESSION_HPP2627#include "memory/allocation.hpp"282930// Interface for a compression implementation.31class AbstractCompressor : public CHeapObj<mtInternal> {32public:33virtual ~AbstractCompressor() { }3435// Initializes the compressor. Returns a static error message in case of an error.36// Otherwise initializes the needed out and tmp size for the given block size.37virtual char const* init(size_t block_size, size_t* needed_out_size,38size_t* needed_tmp_size) = 0;3940// Does the actual compression. Returns NULL on success and a static error41// message otherwise. Sets the 'compressed_size'.42virtual char const* compress(char* in, size_t in_size, char* out, size_t out_size,43char* tmp, size_t tmp_size, size_t* compressed_size) = 0;44};4546// Interface for a writer implementation.47class AbstractWriter : public CHeapObj<mtInternal> {48public:49virtual ~AbstractWriter() { }5051// Opens the writer. Returns NULL on success and a static error message otherwise.52virtual char const* open_writer() = 0;5354// Does the write. Returns NULL on success and a static error message otherwise.55virtual char const* write_buf(char* buf, ssize_t size) = 0;56};575859// A writer for a file.60class FileWriter : public AbstractWriter {61private:62char const* _path;63bool _overwrite;64int _fd;6566public:67FileWriter(char const* path, bool overwrite) : _path(path), _overwrite(overwrite), _fd(-1) { }6869~FileWriter();7071// Opens the writer. Returns NULL on success and a static error message otherwise.72virtual char const* open_writer();7374// Does the write. Returns NULL on success and a static error message otherwise.75virtual char const* write_buf(char* buf, ssize_t size);76};777879// A compressor using the gzip format.80class GZipCompressor : public AbstractCompressor {81private:82int _level;83size_t _block_size;84bool _is_first;8586void* load_gzip_func(char const* name);8788public:89GZipCompressor(int level) : _level(level), _block_size(0), _is_first(false) {90}9192virtual char const* init(size_t block_size, size_t* needed_out_size,93size_t* needed_tmp_size);9495virtual char const* compress(char* in, size_t in_size, char* out, size_t out_size,96char* tmp, size_t tmp_size, size_t* compressed_size);97};9899100// The data needed to write a single buffer (and compress it optionally).101struct WriteWork {102// The id of the work.103int64_t _id;104105// The input buffer where the raw data is106char* _in;107size_t _in_used;108size_t _in_max;109110// The output buffer where the compressed data is. Is NULL when compression is disabled.111char* _out;112size_t _out_used;113size_t _out_max;114115// The temporary space needed for compression. Is NULL when compression is disabled.116char* _tmp;117size_t _tmp_max;118119// Used to link WriteWorks into lists.120WriteWork* _next;121WriteWork* _prev;122};123124// A list for works.125class WorkList {126private:127WriteWork _head;128129void insert(WriteWork* before, WriteWork* work);130WriteWork* remove(WriteWork* work);131132public:133WorkList();134135// Return true if the list is empty.136bool is_empty() { return _head._next == &_head; }137138// Adds to the beginning of the list.139void add_first(WriteWork* work) { insert(&_head, work); }140141// Adds to the end of the list.142void add_last(WriteWork* work) { insert(_head._prev, work); }143144// Adds so the ids are ordered.145void add_by_id(WriteWork* work);146147// Returns the first element.148WriteWork* first() { return is_empty() ? NULL : _head._next; }149150// Returns the last element.151WriteWork* last() { return is_empty() ? NULL : _head._prev; }152153// Removes the first element. Returns NULL if empty.154WriteWork* remove_first() { return remove(first()); }155156// Removes the last element. Returns NULL if empty.157WriteWork* remove_last() { return remove(first()); }158};159160161class Monitor;162163// This class is used by the DumpWriter class. It supplies the DumpWriter with164// chunks of memory to write the heap dump data into. When the DumpWriter needs a165// new memory chunk, it calls get_new_buffer(), which commits the old chunk used166// and returns a new chunk. The old chunk is then added to a queue to be compressed167// and then written in the background.168class CompressionBackend : StackObj {169bool _active;170char const * _err;171172int _nr_of_threads;173int _works_created;174bool _work_creation_failed;175176int64_t _id_to_write;177int64_t _next_id;178179size_t _in_size;180size_t _max_waste;181size_t _out_size;182size_t _tmp_size;183184size_t _written;185186AbstractWriter* const _writer;187AbstractCompressor* const _compressor;188189Monitor* const _lock;190191WriteWork* _current;192WorkList _to_compress;193WorkList _unused;194WorkList _finished;195196void set_error(char const* new_error);197198WriteWork* allocate_work(size_t in_size, size_t out_size, size_t tmp_size);199void free_work(WriteWork* work);200void free_work_list(WorkList* list);201202void do_foreground_work();203WriteWork* get_work();204void do_compress(WriteWork* work);205void finish_work(WriteWork* work);206207public:208// compressor can be NULL if no compression is used.209// Takes ownership of the writer and compressor.210// block_size is the buffer size of a WriteWork.211// max_waste is the maximum number of bytes to leave212// empty in the buffer when it is written.213CompressionBackend(AbstractWriter* writer, AbstractCompressor* compressor,214size_t block_size, size_t max_waste);215216~CompressionBackend();217218size_t get_written() const { return _written; }219220char const* error() const { return _err; }221222// Commits the old buffer (using the value in *used) and sets up a new one.223void get_new_buffer(char** buffer, size_t* used, size_t* max);224225// The entry point for a worker thread.226void thread_loop();227228// Shuts down the backend, releasing all threads.229void deactivate();230};231232233#endif // SHARE_SERVICES_HEAPDUMPERCOMPRESSION_HPP234235236