Path: blob/master/src/hotspot/share/logging/logStream.cpp
40930 views
/*1* Copyright (c) 2016, 2021, Oracle and/or its affiliates. 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#include "precompiled.hpp"25#include "logging/log.hpp"26#include "logging/logStream.hpp"27#include "runtime/os.hpp"28#include "utilities/align.hpp"2930LogStream::LineBuffer::LineBuffer()31: _buf(_smallbuf), _cap(sizeof(_smallbuf)), _pos(0)32{33_buf[0] = '\0';34}3536LogStream::LineBuffer::~LineBuffer() {37assert(_pos == 0, "still outstanding bytes in the line buffer");38if (_buf != _smallbuf) {39os::free(_buf);40}41}4243// try_ensure_cap tries to enlarge the capacity of the internal buffer44// to the given atleast value. May fail if either OOM happens or atleast45// is larger than a reasonable max of 1 M. Caller must not assume46// capacity without checking.47void LogStream::LineBuffer::try_ensure_cap(size_t atleast) {48assert(_cap >= sizeof(_smallbuf), "sanity");49if (_cap < atleast) {50// Cap out at a reasonable max to prevent runaway leaks.51const size_t reasonable_max = 1 * M;52assert(_cap <= reasonable_max, "sanity");53if (_cap == reasonable_max) {54return;55}5657const size_t additional_expansion = 256;58size_t newcap = align_up(atleast + additional_expansion, additional_expansion);59if (newcap > reasonable_max) {60log_info(logging)("Suspiciously long log line: \"%.100s%s",61_buf, (_pos >= 100 ? "..." : ""));62newcap = reasonable_max;63}6465char* const newbuf = (char*) os::malloc(newcap, mtLogging);66if (newbuf == NULL) { // OOM. Leave object unchanged.67return;68}69if (_pos > 0) { // preserve old content70memcpy(newbuf, _buf, _pos + 1); // ..including trailing zero71}72if (_buf != _smallbuf) {73os::free(_buf);74}75_buf = newbuf;76_cap = newcap;77}78assert(_cap >= atleast, "sanity");79}8081void LogStream::LineBuffer::append(const char* s, size_t len) {82assert(_buf[_pos] == '\0', "sanity");83assert(_pos < _cap, "sanity");84const size_t minimum_capacity_needed = _pos + len + 1;85try_ensure_cap(minimum_capacity_needed);86// try_ensure_cap may not have enlarged the capacity to the full requested87// extend or may have not worked at all. In that case, just gracefully work88// with what we have already; just truncate if necessary.89if (_cap < minimum_capacity_needed) {90len = _cap - _pos - 1;91if (len == 0) {92return;93}94}95memcpy(_buf + _pos, s, len);96_pos += len;97_buf[_pos] = '\0';98}99100void LogStream::LineBuffer::reset() {101_pos = 0;102_buf[_pos] = '\0';103}104105void LogStream::write(const char* s, size_t len) {106if (len > 0 && s[len - 1] == '\n') {107_current_line.append(s, len - 1); // omit the newline.108_log_handle.print("%s", _current_line.buffer());109_current_line.reset();110} else {111_current_line.append(s, len);112}113update_position(s, len);114}115116// Destructor writes any unfinished output left in the line buffer.117LogStream::~LogStream() {118if (_current_line.is_empty() == false) {119_log_handle.print("%s", _current_line.buffer());120_current_line.reset();121}122}123124125126127