src/share/vm/utilities/ostream.cpp

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 435
a61af66fc99e
child 515
092ea87cc974
child 535
c7c777385a15
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 1997-2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_ostream.cpp.incl"
    28 extern "C" void jio_print(const char* s); // Declarationtion of jvm method
    30 outputStream::outputStream(int width) {
    31   _width       = width;
    32   _position    = 0;
    33   _newlines    = 0;
    34   _precount    = 0;
    35   _indentation = 0;
    36 }
    38 outputStream::outputStream(int width, bool has_time_stamps) {
    39   _width       = width;
    40   _position    = 0;
    41   _newlines    = 0;
    42   _precount    = 0;
    43   _indentation = 0;
    44   if (has_time_stamps)  _stamp.update();
    45 }
    47 void outputStream::update_position(const char* s, size_t len) {
    48   for (size_t i = 0; i < len; i++) {
    49     char ch = s[i];
    50     if (ch == '\n') {
    51       _newlines += 1;
    52       _precount += _position + 1;
    53       _position = 0;
    54     } else if (ch == '\t') {
    55       _position += 8;
    56       _precount -= 7;  // invariant:  _precount + _position == total count
    57     } else {
    58       _position += 1;
    59     }
    60   }
    61 }
    63 // Execute a vsprintf, using the given buffer if necessary.
    64 // Return a pointer to the formatted string.
    65 const char* outputStream::do_vsnprintf(char* buffer, size_t buflen,
    66                                        const char* format, va_list ap,
    67                                        bool add_cr,
    68                                        size_t& result_len) {
    69   const char* result;
    70   if (add_cr)  buflen--;
    71   if (!strchr(format, '%')) {
    72     // constant format string
    73     result = format;
    74     result_len = strlen(result);
    75     if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
    76   } else if (format[0] == '%' && format[1] == 's' && format[2] == '\0') {
    77     // trivial copy-through format string
    78     result = va_arg(ap, const char*);
    79     result_len = strlen(result);
    80     if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
    81   } else if (vsnprintf(buffer, buflen, format, ap) >= 0) {
    82     result = buffer;
    83     result_len = strlen(result);
    84   } else {
    85     DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
    86     result = buffer;
    87     result_len = buflen - 1;
    88     buffer[result_len] = 0;
    89   }
    90   if (add_cr) {
    91     if (result != buffer) {
    92       strncpy(buffer, result, buflen);
    93       result = buffer;
    94     }
    95     buffer[result_len++] = '\n';
    96     buffer[result_len] = 0;
    97   }
    98   return result;
    99 }
   101 void outputStream::print(const char* format, ...) {
   102   char buffer[O_BUFLEN];
   103   va_list ap;
   104   va_start(ap, format);
   105   size_t len;
   106   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len);
   107   write(str, len);
   108   va_end(ap);
   109 }
   111 void outputStream::print_cr(const char* format, ...) {
   112   char buffer[O_BUFLEN];
   113   va_list ap;
   114   va_start(ap, format);
   115   size_t len;
   116   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len);
   117   write(str, len);
   118   va_end(ap);
   119 }
   121 void outputStream::vprint(const char *format, va_list argptr) {
   122   char buffer[O_BUFLEN];
   123   size_t len;
   124   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len);
   125   write(str, len);
   126 }
   128 void outputStream::vprint_cr(const char* format, va_list argptr) {
   129   char buffer[O_BUFLEN];
   130   size_t len;
   131   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len);
   132   write(str, len);
   133 }
   135 void outputStream::fill_to(int col) {
   136   while (position() < col) sp();
   137 }
   139 void outputStream::put(char ch) {
   140   assert(ch != 0, "please fix call site");
   141   char buf[] = { ch, '\0' };
   142   write(buf, 1);
   143 }
   145 void outputStream::sp() {
   146   this->write(" ", 1);
   147 }
   149 void outputStream::cr() {
   150   this->write("\n", 1);
   151 }
   153 void outputStream::stamp() {
   154   if (! _stamp.is_updated()) {
   155     _stamp.update(); // start at 0 on first call to stamp()
   156   }
   158   // outputStream::stamp() may get called by ostream_abort(), use snprintf
   159   // to avoid allocating large stack buffer in print().
   160   char buf[40];
   161   jio_snprintf(buf, sizeof(buf), "%.3f", _stamp.seconds());
   162   print_raw(buf);
   163 }
   165 void outputStream::date_stamp(bool guard,
   166                               const char* prefix,
   167                               const char* suffix) {
   168   if (!guard) {
   169     return;
   170   }
   171   print_raw(prefix);
   172   static const char error_time[] = "yyyy-mm-ddThh:mm:ss.mmm+zzzz";
   173   static const int buffer_length = 32;
   174   char buffer[buffer_length];
   175   const char* iso8601_result = os::iso8601_time(buffer, buffer_length);
   176   if (iso8601_result != NULL) {
   177     print_raw(buffer);
   178   } else {
   179     print_raw(error_time);
   180   }
   181   print_raw(suffix);
   182   return;
   183 }
   185 void outputStream::indent() {
   186   while (_position < _indentation) sp();
   187 }
   189 void outputStream::print_jlong(jlong value) {
   190   // N.B. Same as INT64_FORMAT
   191   print(os::jlong_format_specifier(), value);
   192 }
   194 void outputStream::print_julong(julong value) {
   195   // N.B. Same as UINT64_FORMAT
   196   print(os::julong_format_specifier(), value);
   197 }
   199 stringStream::stringStream(size_t initial_size) : outputStream() {
   200   buffer_length = initial_size;
   201   buffer        = NEW_RESOURCE_ARRAY(char, buffer_length);
   202   buffer_pos    = 0;
   203   buffer_fixed  = false;
   204 }
   206 // useful for output to fixed chunks of memory, such as performance counters
   207 stringStream::stringStream(char* fixed_buffer, size_t fixed_buffer_size) : outputStream() {
   208   buffer_length = fixed_buffer_size;
   209   buffer        = fixed_buffer;
   210   buffer_pos    = 0;
   211   buffer_fixed  = true;
   212 }
   214 void stringStream::write(const char* s, size_t len) {
   215   size_t write_len = len;               // number of non-null bytes to write
   216   size_t end = buffer_pos + len + 1;    // position after write and final '\0'
   217   if (end > buffer_length) {
   218     if (buffer_fixed) {
   219       // if buffer cannot resize, silently truncate
   220       end = buffer_length;
   221       write_len = end - buffer_pos - 1; // leave room for the final '\0'
   222     } else {
   223       // For small overruns, double the buffer.  For larger ones,
   224       // increase to the requested size.
   225       if (end < buffer_length * 2) {
   226         end = buffer_length * 2;
   227       }
   228       char* oldbuf = buffer;
   229       buffer = NEW_RESOURCE_ARRAY(char, end);
   230       strncpy(buffer, oldbuf, buffer_pos);
   231       buffer_length = end;
   232     }
   233   }
   234   // invariant: buffer is always null-terminated
   235   guarantee(buffer_pos + write_len + 1 <= buffer_length, "stringStream oob");
   236   buffer[buffer_pos + write_len] = 0;
   237   strncpy(buffer + buffer_pos, s, write_len);
   238   buffer_pos += write_len;
   240   // Note that the following does not depend on write_len.
   241   // This means that position and count get updated
   242   // even when overflow occurs.
   243   update_position(s, len);
   244 }
   246 char* stringStream::as_string() {
   247   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1);
   248   strncpy(copy, buffer, buffer_pos);
   249   copy[buffer_pos] = 0;  // terminating null
   250   return copy;
   251 }
   253 stringStream::~stringStream() {}
   255 xmlStream*   xtty;
   256 outputStream* tty;
   257 outputStream* gclog_or_tty;
   258 extern Mutex* tty_lock;
   260 fileStream::fileStream(const char* file_name) {
   261   _file = fopen(file_name, "w");
   262   _need_close = true;
   263 }
   265 void fileStream::write(const char* s, size_t len) {
   266   if (_file != NULL)  fwrite(s, 1, len, _file);
   267   update_position(s, len);
   268 }
   270 fileStream::~fileStream() {
   271   if (_file != NULL) {
   272     if (_need_close) fclose(_file);
   273     _file = NULL;
   274   }
   275 }
   277 void fileStream::flush() {
   278   fflush(_file);
   279 }
   281 fdStream::fdStream(const char* file_name) {
   282   _fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
   283   _need_close = true;
   284 }
   286 fdStream::~fdStream() {
   287   if (_fd != -1) {
   288     if (_need_close) close(_fd);
   289     _fd = -1;
   290   }
   291 }
   293 void fdStream::write(const char* s, size_t len) {
   294   if (_fd != -1) ::write(_fd, s, (int)len);
   295   update_position(s, len);
   296 }
   298 defaultStream* defaultStream::instance = NULL;
   299 int defaultStream::_output_fd = 1;
   300 int defaultStream::_error_fd  = 2;
   301 FILE* defaultStream::_output_stream = stdout;
   302 FILE* defaultStream::_error_stream  = stderr;
   304 #define LOG_MAJOR_VERSION 160
   305 #define LOG_MINOR_VERSION 1
   307 void defaultStream::init() {
   308   _inited = true;
   309   if (LogVMOutput || LogCompilation) {
   310     init_log();
   311   }
   312 }
   314 bool defaultStream::has_log_file() {
   315   // lazily create log file (at startup, LogVMOutput is false even
   316   // if +LogVMOutput is used, because the flags haven't been parsed yet)
   317   // For safer printing during fatal error handling, do not init logfile
   318   // if a VM error has been reported.
   319   if (!_inited && !is_error_reported())  init();
   320   return _log_file != NULL;
   321 }
   323 static const char* make_log_name(const char* log_name, const char* force_directory, char* buf) {
   324   const char* basename = log_name;
   325   char file_sep = os::file_separator()[0];
   326   const char* cp;
   327   for (cp = log_name; *cp != '\0'; cp++) {
   328     if (*cp == '/' || *cp == file_sep) {
   329       basename = cp+1;
   330     }
   331   }
   332   const char* nametail = log_name;
   334   strcpy(buf, "");
   335   if (force_directory != NULL) {
   336     strcat(buf, force_directory);
   337     strcat(buf, os::file_separator());
   338     nametail = basename;       // completely skip directory prefix
   339   }
   341   const char* star = strchr(basename, '*');
   342   int star_pos = (star == NULL) ? -1 : (star - nametail);
   344   if (star_pos >= 0) {
   345     // convert foo*bar.log to foo123bar.log
   346     int buf_pos = (int) strlen(buf);
   347     strncpy(&buf[buf_pos], nametail, star_pos);
   348     sprintf(&buf[buf_pos + star_pos], "%u", os::current_process_id());
   349     nametail += star_pos + 1;  // skip prefix and star
   350   }
   352   strcat(buf, nametail);      // append rest of name, or all of name
   353   return buf;
   354 }
   356 void defaultStream::init_log() {
   357   // %%% Need a MutexLocker?
   358   const char* log_name = LogFile != NULL ? LogFile : "hotspot.log";
   359   char buf[O_BUFLEN*2];
   360   const char* try_name = make_log_name(log_name, NULL, buf);
   361   fileStream* file = new(ResourceObj::C_HEAP) fileStream(try_name);
   362   if (!file->is_open()) {
   363     // Try again to open the file.
   364     char warnbuf[O_BUFLEN*2];
   365     sprintf(warnbuf, "Warning:  Cannot open log file: %s\n", try_name);
   366     // Note:  This feature is for maintainer use only.  No need for L10N.
   367     jio_print(warnbuf);
   368     try_name = make_log_name("hs_pid*.log", os::get_temp_directory(), buf);
   369     sprintf(warnbuf, "Warning:  Forcing option -XX:LogFile=%s\n", try_name);
   370     jio_print(warnbuf);
   371     delete file;
   372     file = new(ResourceObj::C_HEAP) fileStream(try_name);
   373   }
   374   if (file->is_open()) {
   375     _log_file = file;
   376     xmlStream* xs = new(ResourceObj::C_HEAP) xmlStream(file);
   377     _outer_xmlStream = xs;
   378     if (this == tty)  xtty = xs;
   379     // Write XML header.
   380     xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
   381     // (For now, don't bother to issue a DTD for this private format.)
   382     jlong time_ms = os::javaTimeMillis() - tty->time_stamp().milliseconds();
   383     // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if
   384     // we ever get round to introduce that method on the os class
   385     xs->head("hotspot_log version='%d %d'"
   386              " process='%d' time_ms='"INT64_FORMAT"'",
   387              LOG_MAJOR_VERSION, LOG_MINOR_VERSION,
   388              os::current_process_id(), time_ms);
   389     // Write VM version header immediately.
   390     xs->head("vm_version");
   391     xs->head("name"); xs->text("%s", VM_Version::vm_name()); xs->cr();
   392     xs->tail("name");
   393     xs->head("release"); xs->text("%s", VM_Version::vm_release()); xs->cr();
   394     xs->tail("release");
   395     xs->head("info"); xs->text("%s", VM_Version::internal_vm_info_string()); xs->cr();
   396     xs->tail("info");
   397     xs->tail("vm_version");
   398     // Record information about the command-line invocation.
   399     xs->head("vm_arguments");  // Cf. Arguments::print_on()
   400     if (Arguments::num_jvm_flags() > 0) {
   401       xs->head("flags");
   402       Arguments::print_jvm_flags_on(xs->text());
   403       xs->tail("flags");
   404     }
   405     if (Arguments::num_jvm_args() > 0) {
   406       xs->head("args");
   407       Arguments::print_jvm_args_on(xs->text());
   408       xs->tail("args");
   409     }
   410     if (Arguments::java_command() != NULL) {
   411       xs->head("command"); xs->text()->print_cr("%s", Arguments::java_command());
   412       xs->tail("command");
   413     }
   414     if (Arguments::sun_java_launcher() != NULL) {
   415       xs->head("launcher"); xs->text()->print_cr("%s", Arguments::sun_java_launcher());
   416       xs->tail("launcher");
   417     }
   418     if (Arguments::system_properties() !=  NULL) {
   419       xs->head("properties");
   420       // Print it as a java-style property list.
   421       // System properties don't generally contain newlines, so don't bother with unparsing.
   422       for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
   423         xs->text()->print_cr("%s=%s", p->key(), p->value());
   424       }
   425       xs->tail("properties");
   426     }
   427     xs->tail("vm_arguments");
   428     // tty output per se is grouped under the <tty>...</tty> element.
   429     xs->head("tty");
   430     // All further non-markup text gets copied to the tty:
   431     xs->_text = this;  // requires friend declaration!
   432   } else {
   433     delete(file);
   434     // and leave xtty as NULL
   435     LogVMOutput = false;
   436     DisplayVMOutput = true;
   437     LogCompilation = false;
   438   }
   439 }
   441 // finish_log() is called during normal VM shutdown. finish_log_on_error() is
   442 // called by ostream_abort() after a fatal error.
   443 //
   444 void defaultStream::finish_log() {
   445   xmlStream* xs = _outer_xmlStream;
   446   xs->done("tty");
   448   // Other log forks are appended here, at the End of Time:
   449   CompileLog::finish_log(xs->out());  // write compile logging, if any, now
   451   xs->done("hotspot_log");
   452   xs->flush();
   454   fileStream* file = _log_file;
   455   _log_file = NULL;
   457   delete _outer_xmlStream;
   458   _outer_xmlStream = NULL;
   460   file->flush();
   461   delete file;
   462 }
   464 void defaultStream::finish_log_on_error(char *buf, int buflen) {
   465   xmlStream* xs = _outer_xmlStream;
   467   if (xs && xs->out()) {
   469     xs->done_raw("tty");
   471     // Other log forks are appended here, at the End of Time:
   472     CompileLog::finish_log_on_error(xs->out(), buf, buflen);  // write compile logging, if any, now
   474     xs->done_raw("hotspot_log");
   475     xs->flush();
   477     fileStream* file = _log_file;
   478     _log_file = NULL;
   479     _outer_xmlStream = NULL;
   481     if (file) {
   482       file->flush();
   484       // Can't delete or close the file because delete and fclose aren't
   485       // async-safe. We are about to die, so leave it to the kernel.
   486       // delete file;
   487     }
   488   }
   489 }
   491 intx defaultStream::hold(intx writer_id) {
   492   bool has_log = has_log_file();  // check before locking
   493   if (// impossible, but who knows?
   494       writer_id == NO_WRITER ||
   496       // bootstrap problem
   497       tty_lock == NULL ||
   499       // can't grab a lock or call Thread::current() if TLS isn't initialized
   500       ThreadLocalStorage::thread() == NULL ||
   502       // developer hook
   503       !SerializeVMOutput ||
   505       // VM already unhealthy
   506       is_error_reported() ||
   508       // safepoint == global lock (for VM only)
   509       (SafepointSynchronize::is_synchronizing() &&
   510        Thread::current()->is_VM_thread())
   511       ) {
   512     // do not attempt to lock unless we know the thread and the VM is healthy
   513     return NO_WRITER;
   514   }
   515   if (_writer == writer_id) {
   516     // already held, no need to re-grab the lock
   517     return NO_WRITER;
   518   }
   519   tty_lock->lock_without_safepoint_check();
   520   // got the lock
   521   if (writer_id != _last_writer) {
   522     if (has_log) {
   523       _log_file->bol();
   524       // output a hint where this output is coming from:
   525       _log_file->print_cr("<writer thread='"INTX_FORMAT"'/>", writer_id);
   526     }
   527     _last_writer = writer_id;
   528   }
   529   _writer = writer_id;
   530   return writer_id;
   531 }
   533 void defaultStream::release(intx holder) {
   534   if (holder == NO_WRITER) {
   535     // nothing to release:  either a recursive lock, or we scribbled (too bad)
   536     return;
   537   }
   538   if (_writer != holder) {
   539     return;  // already unlocked, perhaps via break_tty_lock_for_safepoint
   540   }
   541   _writer = NO_WRITER;
   542   tty_lock->unlock();
   543 }
   546 // Yuck:  jio_print does not accept char*/len.
   547 static void call_jio_print(const char* s, size_t len) {
   548   char buffer[O_BUFLEN+100];
   549   if (len > sizeof(buffer)-1) {
   550     warning("increase O_BUFLEN in ostream.cpp -- output truncated");
   551     len = sizeof(buffer)-1;
   552   }
   553   strncpy(buffer, s, len);
   554   buffer[len] = '\0';
   555   jio_print(buffer);
   556 }
   559 void defaultStream::write(const char* s, size_t len) {
   560   intx thread_id = os::current_thread_id();
   561   intx holder = hold(thread_id);
   563   if (DisplayVMOutput &&
   564       (_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) {
   565     // print to output stream. It can be redirected by a vfprintf hook
   566     if (s[len] == '\0') {
   567       jio_print(s);
   568     } else {
   569       call_jio_print(s, len);
   570     }
   571   }
   573   // print to log file
   574   if (has_log_file()) {
   575     int nl0 = _newlines;
   576     xmlTextStream::write(s, len);
   577     // flush the log file too, if there were any newlines
   578     if (nl0 != _newlines){
   579       flush();
   580     }
   581   } else {
   582     update_position(s, len);
   583   }
   585   release(holder);
   586 }
   588 intx ttyLocker::hold_tty() {
   589   if (defaultStream::instance == NULL)  return defaultStream::NO_WRITER;
   590   intx thread_id = os::current_thread_id();
   591   return defaultStream::instance->hold(thread_id);
   592 }
   594 void ttyLocker::release_tty(intx holder) {
   595   if (holder == defaultStream::NO_WRITER)  return;
   596   defaultStream::instance->release(holder);
   597 }
   599 void ttyLocker::break_tty_lock_for_safepoint(intx holder) {
   600   if (defaultStream::instance != NULL &&
   601       defaultStream::instance->writer() == holder) {
   602     if (xtty != NULL) {
   603       xtty->print_cr("<!-- safepoint while printing -->");
   604     }
   605     defaultStream::instance->release(holder);
   606   }
   607   // (else there was no lock to break)
   608 }
   610 void ostream_init() {
   611   if (defaultStream::instance == NULL) {
   612     defaultStream::instance = new(ResourceObj::C_HEAP) defaultStream();
   613     tty = defaultStream::instance;
   615     // We want to ensure that time stamps in GC logs consider time 0
   616     // the time when the JVM is initialized, not the first time we ask
   617     // for a time stamp. So, here, we explicitly update the time stamp
   618     // of tty.
   619     tty->time_stamp().update_to(1);
   620   }
   621 }
   623 void ostream_init_log() {
   624   // For -Xloggc:<file> option - called in runtime/thread.cpp
   625   // Note : this must be called AFTER ostream_init()
   627   gclog_or_tty = tty; // default to tty
   628   if (Arguments::gc_log_filename() != NULL) {
   629     fileStream * gclog = new(ResourceObj::C_HEAP)
   630                            fileStream(Arguments::gc_log_filename());
   631     if (gclog->is_open()) {
   632       // now we update the time stamp of the GC log to be synced up
   633       // with tty.
   634       gclog->time_stamp().update_to(tty->time_stamp().ticks());
   635       gclog_or_tty = gclog;
   636     }
   637   }
   639   // If we haven't lazily initialized the logfile yet, do it now,
   640   // to avoid the possibility of lazy initialization during a VM
   641   // crash, which can affect the stability of the fatal error handler.
   642   defaultStream::instance->has_log_file();
   643 }
   645 // ostream_exit() is called during normal VM exit to finish log files, flush
   646 // output and free resource.
   647 void ostream_exit() {
   648   static bool ostream_exit_called = false;
   649   if (ostream_exit_called)  return;
   650   ostream_exit_called = true;
   651   if (gclog_or_tty != tty) {
   652       delete gclog_or_tty;
   653   }
   654   {
   655       // we temporaly disable PrintMallocFree here
   656       // as otherwise it'll lead to using of almost deleted
   657       // tty or defaultStream::instance in logging facility
   658       // of HeapFree(), see 6391258
   659       DEBUG_ONLY(FlagSetting fs(PrintMallocFree, false);)
   660       if (tty != defaultStream::instance) {
   661           delete tty;
   662       }
   663       if (defaultStream::instance != NULL) {
   664           delete defaultStream::instance;
   665       }
   666   }
   667   tty = NULL;
   668   xtty = NULL;
   669   gclog_or_tty = NULL;
   670   defaultStream::instance = NULL;
   671 }
   673 // ostream_abort() is called by os::abort() when VM is about to die.
   674 void ostream_abort() {
   675   // Here we can't delete gclog_or_tty and tty, just flush their output
   676   if (gclog_or_tty) gclog_or_tty->flush();
   677   if (tty) tty->flush();
   679   if (defaultStream::instance != NULL) {
   680     static char buf[4096];
   681     defaultStream::instance->finish_log_on_error(buf, sizeof(buf));
   682   }
   683 }
   685 staticBufferStream::staticBufferStream(char* buffer, size_t buflen,
   686                                        outputStream *outer_stream) {
   687   _buffer = buffer;
   688   _buflen = buflen;
   689   _outer_stream = outer_stream;
   690 }
   692 void staticBufferStream::write(const char* c, size_t len) {
   693   _outer_stream->print_raw(c, (int)len);
   694 }
   696 void staticBufferStream::flush() {
   697   _outer_stream->flush();
   698 }
   700 void staticBufferStream::print(const char* format, ...) {
   701   va_list ap;
   702   va_start(ap, format);
   703   size_t len;
   704   const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len);
   705   write(str, len);
   706   va_end(ap);
   707 }
   709 void staticBufferStream::print_cr(const char* format, ...) {
   710   va_list ap;
   711   va_start(ap, format);
   712   size_t len;
   713   const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len);
   714   write(str, len);
   715   va_end(ap);
   716 }
   718 void staticBufferStream::vprint(const char *format, va_list argptr) {
   719   size_t len;
   720   const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len);
   721   write(str, len);
   722 }
   724 void staticBufferStream::vprint_cr(const char* format, va_list argptr) {
   725   size_t len;
   726   const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len);
   727   write(str, len);
   728 }
   730 bufferedStream::bufferedStream(size_t initial_size) : outputStream() {
   731   buffer_length = initial_size;
   732   buffer        = NEW_C_HEAP_ARRAY(char, buffer_length);
   733   buffer_pos    = 0;
   734   buffer_fixed  = false;
   735 }
   737 bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size) : outputStream() {
   738   buffer_length = fixed_buffer_size;
   739   buffer        = fixed_buffer;
   740   buffer_pos    = 0;
   741   buffer_fixed  = true;
   742 }
   744 void bufferedStream::write(const char* s, size_t len) {
   745   size_t end = buffer_pos + len;
   746   if (end >= buffer_length) {
   747     if (buffer_fixed) {
   748       // if buffer cannot resize, silently truncate
   749       len = buffer_length - buffer_pos - 1;
   750     } else {
   751       // For small overruns, double the buffer.  For larger ones,
   752       // increase to the requested size.
   753       if (end < buffer_length * 2) {
   754         end = buffer_length * 2;
   755       }
   756       buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end);
   757       buffer_length = end;
   758     }
   759   }
   760   memcpy(buffer + buffer_pos, s, len);
   761   buffer_pos += len;
   762   update_position(s, len);
   763 }
   765 char* bufferedStream::as_string() {
   766   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1);
   767   strncpy(copy, buffer, buffer_pos);
   768   copy[buffer_pos] = 0;  // terminating null
   769   return copy;
   770 }
   772 bufferedStream::~bufferedStream() {
   773   if (!buffer_fixed) {
   774     FREE_C_HEAP_ARRAY(char, buffer);
   775   }
   776 }
   778 #ifndef PRODUCT
   780 #if defined(SOLARIS) || defined(LINUX)
   781 #include <sys/types.h>
   782 #include <sys/socket.h>
   783 #include <netinet/in.h>
   784 #include <arpa/inet.h>
   785 #endif
   787 // Network access
   788 networkStream::networkStream() {
   790   _socket = -1;
   792   hpi::initialize_socket_library();
   794   int result = hpi::socket(AF_INET, SOCK_STREAM, 0);
   795   if (result <= 0) {
   796     assert(false, "Socket could not be created!");
   797   } else {
   798     _socket = result;
   799   }
   800 }
   802 int networkStream::read(char *buf, size_t len) {
   803   return hpi::recv(_socket, buf, (int)len, 0);
   804 }
   806 void networkStream::flush() {
   807   if (size() != 0) {
   808     hpi::send(_socket, (char *)base(), (int)size(), 0);
   809   }
   810   reset();
   811 }
   813 networkStream::~networkStream() {
   814   close();
   815 }
   817 void networkStream::close() {
   818   if (_socket != -1) {
   819     flush();
   820     hpi::socket_close(_socket);
   821     _socket = -1;
   822   }
   823 }
   825 bool networkStream::connect(const char *ip, short port) {
   827   struct sockaddr_in server;
   828   server.sin_family = AF_INET;
   829   server.sin_port = htons(port);
   831   server.sin_addr.s_addr = inet_addr(ip);
   832   if (server.sin_addr.s_addr == (unsigned long)-1) {
   833 #ifdef _WINDOWS
   834     struct hostent* host = hpi::get_host_by_name((char*)ip);
   835 #else
   836     struct hostent* host = gethostbyname(ip);
   837 #endif
   838     if (host != NULL) {
   839       memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length);
   840     } else {
   841       return false;
   842     }
   843   }
   846   int result = hpi::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in));
   847   return (result >= 0);
   848 }
   850 #endif

mercurial