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,