ostream.hpp revision 8032:e6d2d68ed87f
133965Sjdp/* 2218822Sdim * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3218822Sdim * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 433965Sjdp * 533965Sjdp * This code is free software; you can redistribute it and/or modify it 633965Sjdp * under the terms of the GNU General Public License version 2 only, as 733965Sjdp * published by the Free Software Foundation. 833965Sjdp * 933965Sjdp * This code is distributed in the hope that it will be useful, but WITHOUT 1033965Sjdp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1133965Sjdp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1233965Sjdp * version 2 for more details (a copy is included in the LICENSE file that 1333965Sjdp * accompanied this code). 1433965Sjdp * 1533965Sjdp * You should have received a copy of the GNU General Public License version 1633965Sjdp * 2 along with this work; if not, write to the Free Software Foundation, 1733965Sjdp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1833965Sjdp * 1933965Sjdp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2033965Sjdp * or visit www.oracle.com if you need additional information or have any 2133965Sjdp * questions. 2233965Sjdp * 23218822Sdim */ 2433965Sjdp 2533965Sjdp#ifndef SHARE_VM_UTILITIES_OSTREAM_HPP 2633965Sjdp#define SHARE_VM_UTILITIES_OSTREAM_HPP 27218822Sdim 2833965Sjdp#include "memory/allocation.hpp" 2933965Sjdp#include "runtime/timer.hpp" 3033965Sjdp 3133965Sjdpclass GCId; 3233965SjdpDEBUG_ONLY(class ResourceMark;) 3333965Sjdp 3433965Sjdp// Output streams for printing 3533965Sjdp// 3633965Sjdp// Printing guidelines: 3733965Sjdp// Where possible, please use tty->print() and tty->print_cr(). 3833965Sjdp// For product mode VM warnings use warning() which internally uses tty. 3933965Sjdp// In places where tty is not initialized yet or too much overhead, 4033965Sjdp// we may use jio_printf: 4133965Sjdp// jio_fprintf(defaultStream::output_stream(), "Message"); 4233965Sjdp// This allows for redirection via -XX:+DisplayVMOutputToStdout and 4333965Sjdp// -XX:+DisplayVMOutputToStderr 4433965Sjdpclass outputStream : public ResourceObj { 4533965Sjdp protected: 4633965Sjdp int _indentation; // current indentation 4733965Sjdp int _width; // width of the page 4833965Sjdp int _position; // position on the current line 4933965Sjdp int _newlines; // number of '\n' output so far 5033965Sjdp julong _precount; // number of chars output, less _position 5133965Sjdp TimeStamp _stamp; // for time stamps 52130561Sobrien 53130561Sobrien void update_position(const char* s, size_t len); 54218822Sdim static const char* do_vsnprintf(char* buffer, size_t buflen, 55130561Sobrien const char* format, va_list ap, 5633965Sjdp bool add_cr, 5733965Sjdp size_t& result_len) ATTRIBUTE_PRINTF(3, 0); 5833965Sjdp 5933965Sjdp public: 6033965Sjdp // creation 6133965Sjdp outputStream(int width = 80); 6233965Sjdp outputStream(int width, bool has_time_stamps); 6333965Sjdp 6433965Sjdp // indentation 6589857Sobrien outputStream& indent(); 66218822Sdim void inc() { _indentation++; }; 6733965Sjdp void dec() { _indentation--; }; 6889857Sobrien void inc(int n) { _indentation += n; }; 6977298Sobrien void dec(int n) { _indentation -= n; }; 7033965Sjdp int indentation() const { return _indentation; } 7133965Sjdp void set_indentation(int i) { _indentation = i; } 7233965Sjdp void fill_to(int col); 7333965Sjdp void move_to(int col, int slop = 6, int min_space = 2); 7433965Sjdp 7533965Sjdp // sizing 7633965Sjdp int width() const { return _width; } 7733965Sjdp int position() const { return _position; } 7833965Sjdp int newlines() const { return _newlines; } 7933965Sjdp julong count() const { return _precount + _position; } 8033965Sjdp void set_count(julong count) { _precount = count - _position; } 8189857Sobrien void set_position(int pos) { _position = pos; } 8289857Sobrien 8333965Sjdp // printing 8433965Sjdp void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); 8533965Sjdp void print_cr(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); 8677298Sobrien void vprint(const char *format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); 8733965Sjdp void vprint_cr(const char* format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); 8833965Sjdp void print_raw(const char* str) { write(str, strlen(str)); } 8933965Sjdp void print_raw(const char* str, int len) { write(str, len); } 9033965Sjdp void print_raw_cr(const char* str) { write(str, strlen(str)); cr(); } 9189857Sobrien void print_raw_cr(const char* str, int len){ write(str, len); cr(); } 9233965Sjdp void print_data(void* data, size_t len, bool with_ascii); 93218822Sdim void put(char ch); 94218822Sdim void sp(int count = 1); 95218822Sdim void cr(); 9633965Sjdp void bol() { if (_position > 0) cr(); } 9789857Sobrien 98218822Sdim // Time stamp 99218822Sdim TimeStamp& time_stamp() { return _stamp; } 10033965Sjdp void stamp(); 10189857Sobrien void stamp(bool guard, const char* prefix, const char* suffix); 102218822Sdim void stamp(bool guard) { 103218822Sdim stamp(guard, "", ": "); 10433965Sjdp } 10589857Sobrien // Date stamp 10633965Sjdp void date_stamp(bool guard, const char* prefix, const char* suffix); 10733965Sjdp // A simplified call that includes a suffix of ": " 10833965Sjdp void date_stamp(bool guard) { 10977298Sobrien date_stamp(guard, "", ": "); 11033965Sjdp } 111218822Sdim void gclog_stamp(const GCId& gc_id); 112218822Sdim 113218822Sdim // portable printing of 64 bit integers 11433965Sjdp void print_jlong(jlong value); 11533965Sjdp void print_julong(julong value); 11633965Sjdp 11777298Sobrien // flushing 11833965Sjdp virtual void flush() {} 11933965Sjdp virtual void write(const char* str, size_t len) = 0; 12033965Sjdp virtual void rotate_log(bool force, outputStream* out = NULL) {} // GC log rotation 12133965Sjdp virtual ~outputStream() {} // close properly on deletion 12233965Sjdp 12333965Sjdp void dec_cr() { dec(); cr(); } 12433965Sjdp void inc_cr() { inc(); cr(); } 12533965Sjdp}; 12633965Sjdp 12733965Sjdp// standard output 12889857Sobrien// ANSI C++ name collision 12933965Sjdpextern outputStream* tty; // tty output 13089857Sobrienextern outputStream* gclog_or_tty; // stream for gc log if -Xloggc:<f>, or tty 13189857Sobrien 13289857Sobrienclass streamIndentor : public StackObj { 13389857Sobrien private: 13489857Sobrien outputStream* _str; 13533965Sjdp int _amount; 13633965Sjdp 13733965Sjdp public: 13833965Sjdp streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) { 13933965Sjdp _str->inc(_amount); 14033965Sjdp } 14133965Sjdp ~streamIndentor() { _str->dec(_amount); } 14233965Sjdp}; 14333965Sjdp 14433965Sjdp 14533965Sjdp// advisory locking for the shared tty stream: 14633965Sjdpclass ttyLocker: StackObj { 14733965Sjdp friend class ttyUnlocker; 14833965Sjdp private: 14933965Sjdp intx _holder; 15033965Sjdp 15133965Sjdp public: 15233965Sjdp static intx hold_tty(); // returns a "holder" token 15333965Sjdp static void release_tty(intx holder); // must witness same token 15433965Sjdp static bool release_tty_if_locked(); // returns true if lock was released 15533965Sjdp static void break_tty_lock_for_safepoint(intx holder); 15633965Sjdp 15777298Sobrien ttyLocker() { _holder = hold_tty(); } 15833965Sjdp ~ttyLocker() { release_tty(_holder); } 15977298Sobrien}; 16033965Sjdp 16133965Sjdp// Release the tty lock if it's held and reacquire it if it was 162130561Sobrien// locked. Used to avoid lock ordering problems. 163130561Sobrienclass ttyUnlocker: StackObj { 164130561Sobrien private: 165130561Sobrien bool _was_locked; 166130561Sobrien public: 167130561Sobrien ttyUnlocker() { 168130561Sobrien _was_locked = ttyLocker::release_tty_if_locked(); 16933965Sjdp } 17033965Sjdp ~ttyUnlocker() { 17133965Sjdp if (_was_locked) { 17233965Sjdp ttyLocker::hold_tty(); 17333965Sjdp } 17433965Sjdp } 17533965Sjdp}; 17633965Sjdp 17733965Sjdp// for writing to strings; buffer will expand automatically 17833965Sjdpclass stringStream : public outputStream { 17933965Sjdp protected: 18033965Sjdp char* buffer; 18133965Sjdp size_t buffer_pos; 182130561Sobrien size_t buffer_length; 183130561Sobrien bool buffer_fixed; 184130561Sobrien DEBUG_ONLY(ResourceMark* rm;) 185130561Sobrien public: 186130561Sobrien stringStream(size_t initial_bufsize = 256); 187130561Sobrien stringStream(char* fixed_buffer, size_t fixed_buffer_size); 18833965Sjdp ~stringStream(); 18933965Sjdp virtual void write(const char* c, size_t len); 190130561Sobrien size_t size() { return buffer_pos; } 191130561Sobrien const char* base() { return buffer; } 192130561Sobrien void reset() { buffer_pos = 0; _precount = 0; _position = 0; } 193130561Sobrien char* as_string(); 19433965Sjdp}; 19533965Sjdp 196130561Sobrienclass fileStream : public outputStream { 197130561Sobrien protected: 19833965Sjdp FILE* _file; 19933965Sjdp bool _need_close; 200130561Sobrien public: 201130561Sobrien fileStream() { _file = NULL; _need_close = false; } 20233965Sjdp fileStream(const char* file_name); 20377298Sobrien fileStream(const char* file_name, const char* opentype); 204130561Sobrien fileStream(FILE* file, bool need_close = false) { _file = file; _need_close = need_close; } 205130561Sobrien ~fileStream(); 206130561Sobrien bool is_open() const { return _file != NULL; } 207130561Sobrien void set_need_close(bool b) { _need_close = b;} 208130561Sobrien virtual void write(const char* c, size_t len); 209130561Sobrien size_t read(void *data, size_t size, size_t count) { return ::fread(data, size, count, _file); } 210130561Sobrien char* readln(char *data, int count); 211130561Sobrien int eof() { return feof(_file); } 212130561Sobrien long fileSize(); 21333965Sjdp void rewind() { ::rewind(_file); } 21460484Sobrien void flush(); 21577298Sobrien}; 21633965Sjdp 217130561SobrienCDS_ONLY(extern fileStream* classlist_file;) 21833965Sjdp 21933965Sjdp// unlike fileStream, fdStream does unbuffered I/O by calling 220// open() and write() directly. It is async-safe, but output 221// from multiple thread may be mixed together. Used by fatal 222// error handler. 223class fdStream : public outputStream { 224 protected: 225 int _fd; 226 bool _need_close; 227 public: 228 fdStream(const char* file_name); 229 fdStream(int fd = -1) { _fd = fd; _need_close = false; } 230 ~fdStream(); 231 bool is_open() const { return _fd != -1; } 232 void set_fd(int fd) { _fd = fd; _need_close = false; } 233 int fd() const { return _fd; } 234 virtual void write(const char* c, size_t len); 235 void flush() {}; 236}; 237 238class gcLogFileStream : public fileStream { 239 protected: 240 const char* _file_name; 241 jlong _bytes_written; 242 uintx _cur_file_num; // current logfile rotation number, from 0 to NumberOfGCLogFiles-1 243 public: 244 gcLogFileStream(const char* file_name); 245 ~gcLogFileStream(); 246 virtual void write(const char* c, size_t len); 247 virtual void rotate_log(bool force, outputStream* out = NULL); 248 void dump_loggc_header(); 249 250 /* If "force" sets true, force log file rotation from outside JVM */ 251 bool should_rotate(bool force) { 252 return force || 253 ((GCLogFileSize != 0) && (_bytes_written >= (jlong)GCLogFileSize)); 254 } 255}; 256 257#ifndef PRODUCT 258// unit test for checking -Xloggc:<filename> parsing result 259void test_loggc_filename(); 260#endif 261 262void ostream_init(); 263void ostream_init_log(); 264void ostream_exit(); 265void ostream_abort(); 266 267// staticBufferStream uses a user-supplied buffer for all formatting. 268// Used for safe formatting during fatal error handling. Not MT safe. 269// Do not share the stream between multiple threads. 270class staticBufferStream : public outputStream { 271 private: 272 char* _buffer; 273 size_t _buflen; 274 outputStream* _outer_stream; 275 public: 276 staticBufferStream(char* buffer, size_t buflen, 277 outputStream *outer_stream); 278 ~staticBufferStream() {}; 279 virtual void write(const char* c, size_t len); 280 void flush(); 281 void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); 282 void print_cr(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); 283 void vprint(const char *format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); 284 void vprint_cr(const char* format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); 285}; 286 287// In the non-fixed buffer case an underlying buffer will be created and 288// managed in C heap. Not MT-safe. 289class bufferedStream : public outputStream { 290 protected: 291 char* buffer; 292 size_t buffer_pos; 293 size_t buffer_max; 294 size_t buffer_length; 295 bool buffer_fixed; 296 public: 297 bufferedStream(size_t initial_bufsize = 256, size_t bufmax = 1024*1024*10); 298 bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax = 1024*1024*10); 299 ~bufferedStream(); 300 virtual void write(const char* c, size_t len); 301 size_t size() { return buffer_pos; } 302 const char* base() { return buffer; } 303 void reset() { buffer_pos = 0; _precount = 0; _position = 0; } 304 char* as_string(); 305}; 306 307#define O_BUFLEN 2000 // max size of output of individual print() methods 308 309#ifndef PRODUCT 310 311class networkStream : public bufferedStream { 312 313 private: 314 int _socket; 315 316 public: 317 networkStream(); 318 ~networkStream(); 319 320 bool connect(const char *host, short port); 321 bool is_open() const { return _socket != -1; } 322 int read(char *buf, size_t len); 323 void close(); 324 virtual void flush(); 325}; 326 327#endif 328 329#endif // SHARE_VM_UTILITIES_OSTREAM_HPP 330