| 1 | /* |
| 2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 20 | * or visit www.oracle.com if you need additional information or have any |
| 21 | * questions. |
| 22 | * |
| 23 | */ |
| 24 | |
| 25 | #ifndef SHARE_UTILITIES_OSTREAM_HPP |
| 26 | #define SHARE_UTILITIES_OSTREAM_HPP |
| 27 | |
| 28 | #include "memory/allocation.hpp" |
| 29 | #include "runtime/timer.hpp" |
| 30 | #include "utilities/globalDefinitions.hpp" |
| 31 | |
| 32 | DEBUG_ONLY(class ResourceMark;) |
| 33 | |
| 34 | // Output streams for printing |
| 35 | // |
| 36 | // Printing guidelines: |
| 37 | // Where possible, please use tty->print() and tty->print_cr(). |
| 38 | // For product mode VM warnings use warning() which internally uses tty. |
| 39 | // In places where tty is not initialized yet or too much overhead, |
| 40 | // we may use jio_printf: |
| 41 | // jio_fprintf(defaultStream::output_stream(), "Message"); |
| 42 | // This allows for redirection via -XX:+DisplayVMOutputToStdout and |
| 43 | // -XX:+DisplayVMOutputToStderr |
| 44 | class outputStream : public ResourceObj { |
| 45 | private: |
| 46 | outputStream(const outputStream&); |
| 47 | outputStream& operator=(const outputStream&); |
| 48 | |
| 49 | protected: |
| 50 | int _indentation; // current indentation |
| 51 | int _width; // width of the page |
| 52 | int _position; // position on the current line |
| 53 | int _newlines; // number of '\n' output so far |
| 54 | julong _precount; // number of chars output, less _position |
| 55 | TimeStamp _stamp; // for time stamps |
| 56 | char* _scratch; // internal scratch buffer for printf |
| 57 | size_t _scratch_len; // size of internal scratch buffer |
| 58 | |
| 59 | void update_position(const char* s, size_t len); |
| 60 | static const char* do_vsnprintf(char* buffer, size_t buflen, |
| 61 | const char* format, va_list ap, |
| 62 | bool add_cr, |
| 63 | size_t& result_len) ATTRIBUTE_PRINTF(3, 0); |
| 64 | |
| 65 | // calls do_vsnprintf and writes output to stream; uses an on-stack buffer. |
| 66 | void do_vsnprintf_and_write_with_automatic_buffer(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0); |
| 67 | // calls do_vsnprintf and writes output to stream; uses the user-provided buffer; |
| 68 | void do_vsnprintf_and_write_with_scratch_buffer(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0); |
| 69 | // calls do_vsnprintf, then writes output to stream. |
| 70 | void do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0); |
| 71 | |
| 72 | public: |
| 73 | // creation |
| 74 | outputStream(int width = 80); |
| 75 | outputStream(int width, bool has_time_stamps); |
| 76 | |
| 77 | // indentation |
| 78 | outputStream& indent(); |
| 79 | void inc() { _indentation++; }; |
| 80 | void dec() { _indentation--; }; |
| 81 | void inc(int n) { _indentation += n; }; |
| 82 | void dec(int n) { _indentation -= n; }; |
| 83 | int indentation() const { return _indentation; } |
| 84 | void set_indentation(int i) { _indentation = i; } |
| 85 | void fill_to(int col); |
| 86 | void move_to(int col, int slop = 6, int min_space = 2); |
| 87 | |
| 88 | // sizing |
| 89 | int width() const { return _width; } |
| 90 | int position() const { return _position; } |
| 91 | int newlines() const { return _newlines; } |
| 92 | julong count() const { return _precount + _position; } |
| 93 | void set_count(julong count) { _precount = count - _position; } |
| 94 | void set_position(int pos) { _position = pos; } |
| 95 | |
| 96 | // printing |
| 97 | void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
| 98 | void print_cr(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
| 99 | void vprint(const char *format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); |
| 100 | void vprint_cr(const char* format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); |
| 101 | void print_raw(const char* str) { write(str, strlen(str)); } |
| 102 | void print_raw(const char* str, int len) { write(str, len); } |
| 103 | void print_raw_cr(const char* str) { write(str, strlen(str)); cr(); } |
| 104 | void print_raw_cr(const char* str, int len){ write(str, len); cr(); } |
| 105 | void print_data(void* data, size_t len, bool with_ascii); |
| 106 | void put(char ch); |
| 107 | void sp(int count = 1); |
| 108 | void cr(); |
| 109 | void cr_indent(); |
| 110 | void bol() { if (_position > 0) cr(); } |
| 111 | |
| 112 | |
| 113 | // Time stamp |
| 114 | TimeStamp& time_stamp() { return _stamp; } |
| 115 | void stamp(); |
| 116 | void stamp(bool guard, const char* prefix, const char* suffix); |
| 117 | void stamp(bool guard) { |
| 118 | stamp(guard, "" , ": " ); |
| 119 | } |
| 120 | // Date stamp |
| 121 | void date_stamp(bool guard, const char* prefix, const char* suffix); |
| 122 | // A simplified call that includes a suffix of ": " |
| 123 | void date_stamp(bool guard) { |
| 124 | date_stamp(guard, "" , ": " ); |
| 125 | } |
| 126 | |
| 127 | // portable printing of 64 bit integers |
| 128 | void print_jlong(jlong value); |
| 129 | void print_julong(julong value); |
| 130 | |
| 131 | // flushing |
| 132 | virtual void flush() {} |
| 133 | virtual void write(const char* str, size_t len) = 0; |
| 134 | virtual void rotate_log(bool force, outputStream* out = NULL) {} // GC log rotation |
| 135 | virtual ~outputStream() {} // close properly on deletion |
| 136 | |
| 137 | // Caller may specify their own scratch buffer to use for printing; otherwise, |
| 138 | // an automatic buffer on the stack (with O_BUFLEN len) is used. |
| 139 | void set_scratch_buffer(char* p, size_t len) { _scratch = p; _scratch_len = len; } |
| 140 | |
| 141 | void dec_cr() { dec(); cr(); } |
| 142 | void inc_cr() { inc(); cr(); } |
| 143 | }; |
| 144 | |
| 145 | // standard output |
| 146 | // ANSI C++ name collision |
| 147 | extern outputStream* tty; // tty output |
| 148 | |
| 149 | class streamIndentor : public StackObj { |
| 150 | private: |
| 151 | outputStream* _str; |
| 152 | int _amount; |
| 153 | |
| 154 | public: |
| 155 | streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) { |
| 156 | _str->inc(_amount); |
| 157 | } |
| 158 | ~streamIndentor() { _str->dec(_amount); } |
| 159 | }; |
| 160 | |
| 161 | // advisory locking for the shared tty stream: |
| 162 | class ttyLocker: StackObj { |
| 163 | friend class ttyUnlocker; |
| 164 | private: |
| 165 | intx _holder; |
| 166 | |
| 167 | public: |
| 168 | static intx hold_tty(); // returns a "holder" token |
| 169 | static void release_tty(intx holder); // must witness same token |
| 170 | static bool release_tty_if_locked(); // returns true if lock was released |
| 171 | static void break_tty_lock_for_safepoint(intx holder); |
| 172 | |
| 173 | ttyLocker() { _holder = hold_tty(); } |
| 174 | ~ttyLocker() { release_tty(_holder); } |
| 175 | }; |
| 176 | |
| 177 | // Release the tty lock if it's held and reacquire it if it was |
| 178 | // locked. Used to avoid lock ordering problems. |
| 179 | class ttyUnlocker: StackObj { |
| 180 | private: |
| 181 | bool _was_locked; |
| 182 | public: |
| 183 | ttyUnlocker() { |
| 184 | _was_locked = ttyLocker::release_tty_if_locked(); |
| 185 | } |
| 186 | ~ttyUnlocker() { |
| 187 | if (_was_locked) { |
| 188 | ttyLocker::hold_tty(); |
| 189 | } |
| 190 | } |
| 191 | }; |
| 192 | |
| 193 | // for writing to strings; buffer will expand automatically. |
| 194 | // Buffer will always be zero-terminated. |
| 195 | class stringStream : public outputStream { |
| 196 | protected: |
| 197 | char* buffer; |
| 198 | size_t buffer_pos; |
| 199 | size_t buffer_length; |
| 200 | bool buffer_fixed; |
| 201 | |
| 202 | // zero terminate at buffer_pos. |
| 203 | void zero_terminate(); |
| 204 | |
| 205 | public: |
| 206 | // Create a stringStream using an internal buffer of initially initial_bufsize size; |
| 207 | // will be enlarged on demand. There is no maximum cap. |
| 208 | stringStream(size_t initial_bufsize = 256); |
| 209 | // Creates a stringStream using a caller-provided buffer. Will truncate silently if |
| 210 | // it overflows. |
| 211 | stringStream(char* fixed_buffer, size_t fixed_buffer_size); |
| 212 | ~stringStream(); |
| 213 | virtual void write(const char* c, size_t len); |
| 214 | // Return number of characters written into buffer, excluding terminating zero and |
| 215 | // subject to truncation in static buffer mode. |
| 216 | size_t size() const { return buffer_pos; } |
| 217 | const char* base() const { return buffer; } |
| 218 | void reset(); |
| 219 | char* as_string() const; |
| 220 | }; |
| 221 | |
| 222 | class fileStream : public outputStream { |
| 223 | protected: |
| 224 | FILE* _file; |
| 225 | bool _need_close; |
| 226 | public: |
| 227 | fileStream() { _file = NULL; _need_close = false; } |
| 228 | fileStream(const char* file_name); |
| 229 | fileStream(const char* file_name, const char* opentype); |
| 230 | fileStream(FILE* file, bool need_close = false) { _file = file; _need_close = need_close; } |
| 231 | ~fileStream(); |
| 232 | bool is_open() const { return _file != NULL; } |
| 233 | virtual void write(const char* c, size_t len); |
| 234 | size_t read(void *data, size_t size, size_t count) { return ::fread(data, size, count, _file); } |
| 235 | char* readln(char *data, int count); |
| 236 | int eof() { return feof(_file); } |
| 237 | long fileSize(); |
| 238 | void rewind() { ::rewind(_file); } |
| 239 | void flush(); |
| 240 | }; |
| 241 | |
| 242 | CDS_ONLY(extern fileStream* classlist_file;) |
| 243 | |
| 244 | // unlike fileStream, fdStream does unbuffered I/O by calling |
| 245 | // open() and write() directly. It is async-safe, but output |
| 246 | // from multiple thread may be mixed together. Used by fatal |
| 247 | // error handler. |
| 248 | class fdStream : public outputStream { |
| 249 | protected: |
| 250 | int _fd; |
| 251 | public: |
| 252 | fdStream(int fd = -1) : _fd(fd) { } |
| 253 | bool is_open() const { return _fd != -1; } |
| 254 | void set_fd(int fd) { _fd = fd; } |
| 255 | int fd() const { return _fd; } |
| 256 | virtual void write(const char* c, size_t len); |
| 257 | void flush() {}; |
| 258 | }; |
| 259 | |
| 260 | void ostream_init(); |
| 261 | void ostream_init_log(); |
| 262 | void ostream_exit(); |
| 263 | void ostream_abort(); |
| 264 | |
| 265 | // In the non-fixed buffer case an underlying buffer will be created and |
| 266 | // managed in C heap. Not MT-safe. |
| 267 | class bufferedStream : public outputStream { |
| 268 | protected: |
| 269 | char* buffer; |
| 270 | size_t buffer_pos; |
| 271 | size_t buffer_max; |
| 272 | size_t buffer_length; |
| 273 | bool buffer_fixed; |
| 274 | bool truncated; |
| 275 | public: |
| 276 | bufferedStream(size_t initial_bufsize = 256, size_t bufmax = 1024*1024*10); |
| 277 | bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax = 1024*1024*10); |
| 278 | ~bufferedStream(); |
| 279 | virtual void write(const char* c, size_t len); |
| 280 | size_t size() { return buffer_pos; } |
| 281 | const char* base() { return buffer; } |
| 282 | void reset() { buffer_pos = 0; _precount = 0; _position = 0; } |
| 283 | char* as_string(); |
| 284 | }; |
| 285 | |
| 286 | #define O_BUFLEN 2000 // max size of output of individual print() methods |
| 287 | |
| 288 | #ifndef PRODUCT |
| 289 | |
| 290 | class networkStream : public bufferedStream { |
| 291 | |
| 292 | private: |
| 293 | int _socket; |
| 294 | |
| 295 | public: |
| 296 | networkStream(); |
| 297 | ~networkStream(); |
| 298 | |
| 299 | bool connect(const char *host, short port); |
| 300 | bool is_open() const { return _socket != -1; } |
| 301 | int read(char *buf, size_t len); |
| 302 | void close(); |
| 303 | virtual void flush(); |
| 304 | }; |
| 305 | |
| 306 | #endif |
| 307 | |
| 308 | #endif // SHARE_UTILITIES_OSTREAM_HPP |
| 309 | |