src/share/vm/utilities/ostream.cpp

changeset 2964
2a241e764894
parent 2702
8010c8c623ac
child 3156
f08d439fab8c
     1.1 --- a/src/share/vm/utilities/ostream.cpp	Wed Jun 08 21:48:38 2011 -0400
     1.2 +++ b/src/share/vm/utilities/ostream.cpp	Fri Jun 10 15:08:36 2011 -0700
     1.3 @@ -349,7 +349,7 @@
     1.4  fileStream::~fileStream() {
     1.5    if (_file != NULL) {
     1.6      if (_need_close) fclose(_file);
     1.7 -    _file = NULL;
     1.8 +    _file      = NULL;
     1.9    }
    1.10  }
    1.11  
    1.12 @@ -377,6 +377,86 @@
    1.13    update_position(s, len);
    1.14  }
    1.15  
    1.16 +rotatingFileStream::~rotatingFileStream() {
    1.17 +  if (_file != NULL) {
    1.18 +    if (_need_close) fclose(_file);
    1.19 +    _file      = NULL;
    1.20 +    FREE_C_HEAP_ARRAY(char, _file_name);
    1.21 +    _file_name = NULL;
    1.22 +  }
    1.23 +}
    1.24 +
    1.25 +rotatingFileStream::rotatingFileStream(const char* file_name) {
    1.26 +  _cur_file_num = 0;
    1.27 +  _bytes_writen = 0L;
    1.28 +  _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10);
    1.29 +  jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num);
    1.30 +  _file = fopen(_file_name, "w");
    1.31 +  _need_close = true;
    1.32 +}
    1.33 +
    1.34 +rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) {
    1.35 +  _cur_file_num = 0;
    1.36 +  _bytes_writen = 0L;
    1.37 +  _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10);
    1.38 +  jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num);
    1.39 +  _file = fopen(_file_name, opentype);
    1.40 +  _need_close = true;
    1.41 +}
    1.42 +
    1.43 +void rotatingFileStream::write(const char* s, size_t len) {
    1.44 +  if (_file != NULL)  {
    1.45 +    // Make an unused local variable to avoid warning from gcc 4.x compiler.
    1.46 +    size_t count = fwrite(s, 1, len, _file);
    1.47 +    Atomic::add((jlong)count, &_bytes_writen);
    1.48 +  }
    1.49 +  update_position(s, len);
    1.50 +}
    1.51 +
    1.52 +// rotate_log must be called from VMThread at safepoint. In case need change parameters
    1.53 +// for gc log rotation from thread other than VMThread, a sub type of VM_Operation
    1.54 +// should be created and be submitted to VMThread's operation queue. DO NOT call this
    1.55 +// function directly. Currently, it is safe to rotate log at safepoint through VMThread.
    1.56 +// That is, no mutator threads and concurrent GC threads run parallel with VMThread to
    1.57 +// write to gc log file at safepoint. If in future, changes made for mutator threads or
    1.58 +// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
    1.59 +// must be synchronized.
    1.60 +void rotatingFileStream::rotate_log() {
    1.61 +  if (_bytes_writen < (jlong)GCLogFileSize) return;
    1.62 +#ifdef ASSERT
    1.63 +  Thread *thread = Thread::current();
    1.64 +  assert(thread == NULL ||
    1.65 +         (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()),
    1.66 +         "Must be VMThread at safepoint");
    1.67 +#endif
    1.68 +  if (NumberOfGCLogFiles == 1) {
    1.69 +    // rotate in same file
    1.70 +    rewind();
    1.71 +    _bytes_writen = 0L;
    1.72 +    return;
    1.73 +  }
    1.74 +
    1.75 +  // rotate file in names file.0, file.1, file.2, ..., file.<MaxGCLogFileNumbers-1>
    1.76 +  // close current file, rotate to next file
    1.77 +  if (_file != NULL) {
    1.78 +    _cur_file_num ++;
    1.79 +    if (_cur_file_num >= NumberOfGCLogFiles) _cur_file_num = 0;
    1.80 +    jio_snprintf(_file_name, strlen(Arguments::gc_log_filename()) + 10, "%s.%d",
    1.81 +             Arguments::gc_log_filename(), _cur_file_num);
    1.82 +    fclose(_file);
    1.83 +    _file = NULL;
    1.84 +  }
    1.85 +  _file = fopen(_file_name, "w");
    1.86 +  if (_file != NULL) {
    1.87 +    _bytes_writen = 0L;
    1.88 +    _need_close = true;
    1.89 +  } else {
    1.90 +    tty->print_cr("failed to open rotation log file %s due to %s\n",
    1.91 +                  _file_name, strerror(errno));
    1.92 +    _need_close = false;
    1.93 +  }
    1.94 +}
    1.95 +
    1.96  defaultStream* defaultStream::instance = NULL;
    1.97  int defaultStream::_output_fd = 1;
    1.98  int defaultStream::_error_fd  = 2;
    1.99 @@ -749,14 +829,17 @@
   1.100  
   1.101    gclog_or_tty = tty; // default to tty
   1.102    if (Arguments::gc_log_filename() != NULL) {
   1.103 -    fileStream * gclog = new(ResourceObj::C_HEAP)
   1.104 -                           fileStream(Arguments::gc_log_filename());
   1.105 +    fileStream * gclog  = UseGCLogFileRotation ?
   1.106 +                          new(ResourceObj::C_HEAP)
   1.107 +                             rotatingFileStream(Arguments::gc_log_filename()) :
   1.108 +                          new(ResourceObj::C_HEAP)
   1.109 +                             fileStream(Arguments::gc_log_filename());
   1.110      if (gclog->is_open()) {
   1.111        // now we update the time stamp of the GC log to be synced up
   1.112        // with tty.
   1.113        gclog->time_stamp().update_to(tty->time_stamp().ticks());
   1.114 -      gclog_or_tty = gclog;
   1.115      }
   1.116 +    gclog_or_tty = gclog;
   1.117    }
   1.118  
   1.119    // If we haven't lazily initialized the logfile yet, do it now,

mercurial