src/share/vm/utilities/ostream.cpp

Print this page




 352   // even when overflow occurs.
 353   update_position(s, len);
 354 }
 355 
 356 char* stringStream::as_string() {
 357   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos + 1);
 358   strncpy(copy, buffer, buffer_pos);
 359   copy[buffer_pos] = 0;  // terminating null
 360   return copy;
 361 }
 362 
 363 stringStream::~stringStream() {}
 364 
 365 xmlStream*   xtty;
 366 outputStream* tty;
 367 outputStream* gclog_or_tty;
 368 extern Mutex* tty_lock;
 369 
 370 #define EXTRACHARLEN   32
 371 #define CURRENTAPPX    ".current"
 372 #define FILENAMEBUFLEN  1024
 373 // convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
 374 char* get_datetime_string(char *buf, size_t len) {
 375   os::local_time_string(buf, len);
 376   int i = (int)strlen(buf);
 377   while (i-- >= 0) {
 378     if (buf[i] == ' ') buf[i] = '_';
 379     else if (buf[i] == ':') buf[i] = '-';
 380   }
 381   return buf;
 382 }
 383 
 384 static const char* make_log_name_internal(const char* log_name, const char* force_directory,
 385                                                 int pid, const char* tms) {
 386   const char* basename = log_name;
 387   char file_sep = os::file_separator()[0];
 388   const char* cp;
 389   char  pid_text[32];
 390 
 391   for (cp = log_name; *cp != '\0'; cp++) {
 392     if (*cp == '/' || *cp == file_sep) {
 393       basename = cp + 1;
 394     }
 395   }
 396   const char* nametail = log_name;
 397   // Compute buffer length
 398   size_t buffer_length;
 399   if (force_directory != NULL) {
 400     buffer_length = strlen(force_directory) + strlen(os::file_separator()) +
 401                     strlen(basename) + 1;
 402   } else {
 403     buffer_length = strlen(log_name) + 1;
 404   }
 405 





 406   // const char* star = strchr(basename, '*');
 407   const char* pts = strstr(basename, "%p");
 408   int pid_pos = (pts == NULL) ? -1 : (pts - nametail);
 409 
 410   if (pid_pos >= 0) {
 411     jio_snprintf(pid_text, sizeof(pid_text), "pid%u", pid);
 412     buffer_length += strlen(pid_text);
 413   }
 414 
 415   pts = strstr(basename, "%t");
 416   int tms_pos = (pts == NULL) ? -1 : (pts - nametail);
 417   if (tms_pos >= 0) {
 418     buffer_length += strlen(tms);
 419   }
 420 
 421   // Create big enough buffer.
 422   char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
 423 
 424   strcpy(buf, "");
 425   if (force_directory != NULL) {


 473     }
 474   }
 475   strcat(buf, tail);      // append rest of name, or all of name
 476   return buf;
 477 }
 478 
 479 // log_name comes from -XX:LogFile=log_name or -Xloggc:log_name
 480 // in log_name, %p => pid1234 and
 481 //              %t => YYYY-MM-DD_HH-MM-SS
 482 static const char* make_log_name(const char* log_name, const char* force_directory) {
 483   char timestr[32];
 484   get_datetime_string(timestr, sizeof(timestr));
 485   return make_log_name_internal(log_name, force_directory, os::current_process_id(),
 486                                 timestr);
 487 }
 488 
 489 #ifndef PRODUCT
 490 void test_loggc_filename() {
 491   int pid;
 492   char  tms[32];
 493   char  i_result[FILENAMEBUFLEN];
 494   const char* o_result;
 495   get_datetime_string(tms, sizeof(tms));
 496   pid = os::current_process_id();
 497 
 498   // test.log
 499   jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms);
 500   o_result = make_log_name_internal("test.log", NULL, pid, tms);
 501   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
 502   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 503 
 504   // test-%t-%p.log
 505   jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid);
 506   o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms);
 507   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)");
 508   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 509 
 510   // test-%t%p.log
 511   jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid);
 512   o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms);
 513   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)");
 514   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 515 
 516   // %p%t.log
 517   jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms);
 518   o_result = make_log_name_internal("%p%t.log", NULL, pid, tms);
 519   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)");
 520   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 521 
 522   // %p-test.log
 523   jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid);
 524   o_result = make_log_name_internal("%p-test.log", NULL, pid, tms);
 525   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)");
 526   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 527 
 528   // %t.log
 529   jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms);
 530   o_result = make_log_name_internal("%t.log", NULL, pid, tms);
 531   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
 532   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 533 }
 534 #endif // PRODUCT
 535 
 536 fileStream::fileStream(const char* file_name) {
 537   _file = fopen(file_name, "w");
 538   if (_file != NULL) {
 539     _need_close = true;
 540   } else {
 541     warning("Cannot open file %s due to %s\n", file_name, strerror(errno));
 542     _need_close = false;
 543   }
 544 }
 545 
 546 fileStream::fileStream(const char* file_name, const char* opentype) {
 547   _file = fopen(file_name, opentype);
 548   if (_file != NULL) {
 549     _need_close = true;


 621     CommandLineFlags::printSetFlags(this);
 622   }
 623 }
 624 
 625 gcLogFileStream::~gcLogFileStream() {
 626   if (_file != NULL) {
 627     if (_need_close) fclose(_file);
 628     _file = NULL;
 629   }
 630   if (_file_name != NULL) {
 631     FREE_C_HEAP_ARRAY(char, _file_name, mtInternal);
 632     _file_name = NULL;
 633   }
 634 }
 635 
 636 gcLogFileStream::gcLogFileStream(const char* file_name) {
 637   _cur_file_num = 0;
 638   _bytes_written = 0L;
 639   _file_name = make_log_name(file_name, NULL);
 640 







 641   // gc log file rotation
 642   if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
 643     char tempbuf[FILENAMEBUFLEN];
 644     jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
 645     _file = fopen(tempbuf, "w");
 646   } else {
 647     _file = fopen(_file_name, "w");
 648   }
 649   if (_file != NULL) {
 650     _need_close = true;
 651     dump_loggc_header();
 652   } else {
 653     warning("Cannot open file %s due to %s\n", _file_name, strerror(errno));
 654     _need_close = false;
 655   }
 656 }
 657 
 658 void gcLogFileStream::write(const char* s, size_t len) {
 659   if (_file != NULL) {
 660     size_t count = fwrite(s, 1, len, _file);
 661     _bytes_written += count;
 662   }
 663   update_position(s, len);
 664 }
 665 
 666 // rotate_log must be called from VMThread at safepoint. In case need change parameters
 667 // for gc log rotation from thread other than VMThread, a sub type of VM_Operation
 668 // should be created and be submitted to VMThread's operation queue. DO NOT call this
 669 // function directly. Currently, it is safe to rotate log at safepoint through VMThread.
 670 // That is, no mutator threads and concurrent GC threads run parallel with VMThread to
 671 // write to gc log file at safepoint. If in future, changes made for mutator threads or
 672 // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
 673 // must be synchronized.
 674 void gcLogFileStream::rotate_log(bool force, outputStream* out) {
 675   char time_msg[FILENAMEBUFLEN];
 676   char time_str[EXTRACHARLEN];
 677   char current_file_name[FILENAMEBUFLEN];
 678   char renamed_file_name[FILENAMEBUFLEN];
 679 
 680   if (!should_rotate(force)) {
 681     return;
 682   }
 683 
 684 #ifdef ASSERT
 685   Thread *thread = Thread::current();
 686   assert(thread == NULL ||
 687          (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()),
 688          "Must be VMThread at safepoint");
 689 #endif
 690   if (NumberOfGCLogFiles == 1) {
 691     // rotate in same file
 692     rewind();
 693     _bytes_written = 0L;
 694     jio_snprintf(time_msg, sizeof(time_msg), "File  %s rotated at %s\n",
 695                  _file_name, os::local_time_string((char *)time_str, sizeof(time_str)));
 696     write(time_msg, strlen(time_msg));
 697 
 698     if (out != NULL) {
 699       out->print("%s", time_msg);
 700     }
 701 
 702     dump_loggc_header();
 703     return;
 704   }
 705 
 706 #if defined(_WINDOWS)
 707 #ifndef F_OK
 708 #define F_OK 0
 709 #endif
 710 #endif // _WINDOWS
 711 
 712   // rotate file in names extended_filename.0, extended_filename.1, ...,
 713   // extended_filename.<NumberOfGCLogFiles - 1>. Current rotation file name will
 714   // have a form of extended_filename.<i>.current where i is the current rotation
 715   // file number. After it reaches max file size, the file will be saved and renamed
 716   // with .current removed from its tail.
 717   size_t filename_len = strlen(_file_name);
 718   if (_file != NULL) {
 719     jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d",
 720                  _file_name, _cur_file_num);
 721     jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
 722                  _file_name, _cur_file_num);







 723 
 724     const char* msg = force ? "GC log rotation request has been received."
 725                             : "GC log file has reached the maximum size.";
 726     jio_snprintf(time_msg, sizeof(time_msg), "%s %s Saved as %s\n",
 727                      os::local_time_string((char *)time_str, sizeof(time_str)),
 728                                                          msg, renamed_file_name);
 729     write(time_msg, strlen(time_msg));
 730 
 731     if (out != NULL) {
 732       out->print("%s", time_msg);
 733     }
 734 
 735     fclose(_file);
 736     _file = NULL;
 737 
 738     bool can_rename = true;
 739     if (access(current_file_name, F_OK) != 0) {
 740       // current file does not exist?
 741       warning("No source file exists, cannot rename\n");
 742       can_rename = false;
 743     }
 744     if (can_rename) {
 745       if (access(renamed_file_name, F_OK) == 0) {
 746         if (remove(renamed_file_name) != 0) {
 747           warning("Could not delete existing file %s\n", renamed_file_name);
 748           can_rename = false;
 749         }
 750       } else {
 751         // file does not exist, ok to rename
 752       }
 753     }
 754     if (can_rename && rename(current_file_name, renamed_file_name) != 0) {
 755       warning("Could not rename %s to %s\n", _file_name, renamed_file_name);
 756     }
 757   }
 758 
 759   _cur_file_num++;
 760   if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0;
 761   jio_snprintf(current_file_name,  filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
 762                _file_name, _cur_file_num);






 763   _file = fopen(current_file_name, "w");
 764 
 765   if (_file != NULL) {
 766     _bytes_written = 0L;
 767     _need_close = true;
 768     // reuse current_file_name for time_msg
 769     jio_snprintf(current_file_name, filename_len + EXTRACHARLEN,
 770                  "%s.%d", _file_name, _cur_file_num);
 771     jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
 772                            os::local_time_string((char *)time_str, sizeof(time_str)),
 773                            current_file_name);
 774     write(time_msg, strlen(time_msg));
 775 
 776     if (out != NULL) {
 777       out->print("%s", time_msg);
 778     }
 779 
 780     dump_loggc_header();
 781     // remove the existing file
 782     if (access(current_file_name, F_OK) == 0) {
 783       if (remove(current_file_name) != 0) {
 784         warning("Could not delete existing file %s\n", current_file_name);
 785       }
 786     }
 787   } else {
 788     warning("failed to open rotation log file %s due to %s\n"
 789             "Turned off GC log file rotation\n",




 352   // even when overflow occurs.
 353   update_position(s, len);
 354 }
 355 
 356 char* stringStream::as_string() {
 357   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos + 1);
 358   strncpy(copy, buffer, buffer_pos);
 359   copy[buffer_pos] = 0;  // terminating null
 360   return copy;
 361 }
 362 
 363 stringStream::~stringStream() {}
 364 
 365 xmlStream*   xtty;
 366 outputStream* tty;
 367 outputStream* gclog_or_tty;
 368 extern Mutex* tty_lock;
 369 
 370 #define EXTRACHARLEN   32
 371 #define CURRENTAPPX    ".current"

 372 // convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
 373 char* get_datetime_string(char *buf, size_t len) {
 374   os::local_time_string(buf, len);
 375   int i = (int)strlen(buf);
 376   while (i-- >= 0) {
 377     if (buf[i] == ' ') buf[i] = '_';
 378     else if (buf[i] == ':') buf[i] = '-';
 379   }
 380   return buf;
 381 }
 382 
 383 static const char* make_log_name_internal(const char* log_name, const char* force_directory,
 384                                                 int pid, const char* tms) {
 385   const char* basename = log_name;
 386   char file_sep = os::file_separator()[0];
 387   const char* cp;
 388   char  pid_text[32];
 389 
 390   for (cp = log_name; *cp != '\0'; cp++) {
 391     if (*cp == '/' || *cp == file_sep) {
 392       basename = cp + 1;
 393     }
 394   }
 395   const char* nametail = log_name;
 396   // Compute buffer length
 397   size_t buffer_length;
 398   if (force_directory != NULL) {
 399     buffer_length = strlen(force_directory) + strlen(os::file_separator()) +
 400                     strlen(basename) + 1;
 401   } else {
 402     buffer_length = strlen(log_name) + 1;
 403   }
 404 
 405   // File name is too long.
 406   if (buffer_length > JVM_MAXPATHLEN) {
 407     return NULL;
 408   }
 409 
 410   // const char* star = strchr(basename, '*');
 411   const char* pts = strstr(basename, "%p");
 412   int pid_pos = (pts == NULL) ? -1 : (pts - nametail);
 413 
 414   if (pid_pos >= 0) {
 415     jio_snprintf(pid_text, sizeof(pid_text), "pid%u", pid);
 416     buffer_length += strlen(pid_text);
 417   }
 418 
 419   pts = strstr(basename, "%t");
 420   int tms_pos = (pts == NULL) ? -1 : (pts - nametail);
 421   if (tms_pos >= 0) {
 422     buffer_length += strlen(tms);
 423   }
 424 
 425   // Create big enough buffer.
 426   char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
 427 
 428   strcpy(buf, "");
 429   if (force_directory != NULL) {


 477     }
 478   }
 479   strcat(buf, tail);      // append rest of name, or all of name
 480   return buf;
 481 }
 482 
 483 // log_name comes from -XX:LogFile=log_name or -Xloggc:log_name
 484 // in log_name, %p => pid1234 and
 485 //              %t => YYYY-MM-DD_HH-MM-SS
 486 static const char* make_log_name(const char* log_name, const char* force_directory) {
 487   char timestr[32];
 488   get_datetime_string(timestr, sizeof(timestr));
 489   return make_log_name_internal(log_name, force_directory, os::current_process_id(),
 490                                 timestr);
 491 }
 492 
 493 #ifndef PRODUCT
 494 void test_loggc_filename() {
 495   int pid;
 496   char  tms[32];
 497   char  i_result[JVM_MAXPATHLEN];
 498   const char* o_result;
 499   get_datetime_string(tms, sizeof(tms));
 500   pid = os::current_process_id();
 501 
 502   // test.log
 503   jio_snprintf(i_result, sizeof(char)*JVM_MAXPATHLEN, "test.log", tms);
 504   o_result = make_log_name_internal("test.log", NULL, pid, tms);
 505   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
 506   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 507 
 508   // test-%t-%p.log
 509   jio_snprintf(i_result, sizeof(char)*JVM_MAXPATHLEN, "test-%s-pid%u.log", tms, pid);
 510   o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms);
 511   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)");
 512   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 513 
 514   // test-%t%p.log
 515   jio_snprintf(i_result, sizeof(char)*JVM_MAXPATHLEN, "test-%spid%u.log", tms, pid);
 516   o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms);
 517   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)");
 518   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 519 
 520   // %p%t.log
 521   jio_snprintf(i_result, sizeof(char)*JVM_MAXPATHLEN, "pid%u%s.log", pid, tms);
 522   o_result = make_log_name_internal("%p%t.log", NULL, pid, tms);
 523   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)");
 524   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 525 
 526   // %p-test.log
 527   jio_snprintf(i_result, sizeof(char)*JVM_MAXPATHLEN, "pid%u-test.log", pid);
 528   o_result = make_log_name_internal("%p-test.log", NULL, pid, tms);
 529   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)");
 530   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 531 
 532   // %t.log
 533   jio_snprintf(i_result, sizeof(char)*JVM_MAXPATHLEN, "%s.log", tms);
 534   o_result = make_log_name_internal("%t.log", NULL, pid, tms);
 535   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
 536   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
 537 }
 538 #endif // PRODUCT
 539 
 540 fileStream::fileStream(const char* file_name) {
 541   _file = fopen(file_name, "w");
 542   if (_file != NULL) {
 543     _need_close = true;
 544   } else {
 545     warning("Cannot open file %s due to %s\n", file_name, strerror(errno));
 546     _need_close = false;
 547   }
 548 }
 549 
 550 fileStream::fileStream(const char* file_name, const char* opentype) {
 551   _file = fopen(file_name, opentype);
 552   if (_file != NULL) {
 553     _need_close = true;


 625     CommandLineFlags::printSetFlags(this);
 626   }
 627 }
 628 
 629 gcLogFileStream::~gcLogFileStream() {
 630   if (_file != NULL) {
 631     if (_need_close) fclose(_file);
 632     _file = NULL;
 633   }
 634   if (_file_name != NULL) {
 635     FREE_C_HEAP_ARRAY(char, _file_name, mtInternal);
 636     _file_name = NULL;
 637   }
 638 }
 639 
 640 gcLogFileStream::gcLogFileStream(const char* file_name) {
 641   _cur_file_num = 0;
 642   _bytes_written = 0L;
 643   _file_name = make_log_name(file_name, NULL);
 644 
 645   if (_file_name == NULL) {
 646     warning("Cannot open file %s: file name is too long.\n", file_name);
 647     _need_close = false;
 648     UseGCLogFileRotation = false;
 649     return;
 650   }
 651 
 652   // gc log file rotation
 653   if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
 654     char tempbuf[JVM_MAXPATHLEN];
 655     jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
 656     _file = fopen(tempbuf, "w");
 657   } else {
 658     _file = fopen(_file_name, "w");
 659   }
 660   if (_file != NULL) {
 661     _need_close = true;
 662     dump_loggc_header();
 663   } else {
 664     warning("Cannot open file %s due to %s\n", _file_name, strerror(errno));
 665     _need_close = false;
 666   }
 667 }
 668 
 669 void gcLogFileStream::write(const char* s, size_t len) {
 670   if (_file != NULL) {
 671     size_t count = fwrite(s, 1, len, _file);
 672     _bytes_written += count;
 673   }
 674   update_position(s, len);
 675 }
 676 
 677 // rotate_log must be called from VMThread at safepoint. In case need change parameters
 678 // for gc log rotation from thread other than VMThread, a sub type of VM_Operation
 679 // should be created and be submitted to VMThread's operation queue. DO NOT call this
 680 // function directly. Currently, it is safe to rotate log at safepoint through VMThread.
 681 // That is, no mutator threads and concurrent GC threads run parallel with VMThread to
 682 // write to gc log file at safepoint. If in future, changes made for mutator threads or
 683 // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
 684 // must be synchronized.
 685 void gcLogFileStream::rotate_log(bool force, outputStream* out) {
 686   char time_msg[O_BUFLEN];
 687   char time_str[EXTRACHARLEN];
 688   char current_file_name[JVM_MAXPATHLEN];
 689   char renamed_file_name[JVM_MAXPATHLEN];
 690 
 691   if (!should_rotate(force)) {
 692     return;
 693   }
 694 
 695 #ifdef ASSERT
 696   Thread *thread = Thread::current();
 697   assert(thread == NULL ||
 698          (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()),
 699          "Must be VMThread at safepoint");
 700 #endif
 701   if (NumberOfGCLogFiles == 1) {
 702     // rotate in same file
 703     rewind();
 704     _bytes_written = 0L;
 705     jio_snprintf(time_msg, sizeof(time_msg), "File  %s rotated at %s\n",
 706                  _file_name, os::local_time_string((char *)time_str, sizeof(time_str)));
 707     write(time_msg, strlen(time_msg));
 708 
 709     if (out != NULL) {
 710       out->print("%s", time_msg);
 711     }
 712 
 713     dump_loggc_header();
 714     return;
 715   }
 716 
 717 #if defined(_WINDOWS)
 718 #ifndef F_OK
 719 #define F_OK 0
 720 #endif
 721 #endif // _WINDOWS
 722 
 723   // rotate file in names extended_filename.0, extended_filename.1, ...,
 724   // extended_filename.<NumberOfGCLogFiles - 1>. Current rotation file name will
 725   // have a form of extended_filename.<i>.current where i is the current rotation
 726   // file number. After it reaches max file size, the file will be saved and renamed
 727   // with .current removed from its tail.

 728   if (_file != NULL) {
 729     jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d",


 730                  _file_name, _cur_file_num);
 731     int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN,
 732                                 "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
 733     if (result >= JVM_MAXPATHLEN) {
 734       warning("Cannot create new log file name: %s: file name is too long.\n",
 735                                                              current_file_name);
 736       return;
 737     }
 738 
 739     const char* msg = force ? "GC log rotation request has been received."
 740                             : "GC log file has reached the maximum size.";
 741     jio_snprintf(time_msg, sizeof(time_msg), "%s %s Saved as %s\n",
 742                      os::local_time_string((char *)time_str, sizeof(time_str)),
 743                                                          msg, renamed_file_name);
 744     write(time_msg, strlen(time_msg));
 745 
 746     if (out != NULL) {
 747       out->print("%s", time_msg);
 748     }
 749 
 750     fclose(_file);
 751     _file = NULL;
 752 
 753     bool can_rename = true;
 754     if (access(current_file_name, F_OK) != 0) {
 755       // current file does not exist?
 756       warning("No source file exists, cannot rename\n");
 757       can_rename = false;
 758     }
 759     if (can_rename) {
 760       if (access(renamed_file_name, F_OK) == 0) {
 761         if (remove(renamed_file_name) != 0) {
 762           warning("Could not delete existing file %s\n", renamed_file_name);
 763           can_rename = false;
 764         }
 765       } else {
 766         // file does not exist, ok to rename
 767       }
 768     }
 769     if (can_rename && rename(current_file_name, renamed_file_name) != 0) {
 770       warning("Could not rename %s to %s\n", _file_name, renamed_file_name);
 771     }
 772   }
 773 
 774   _cur_file_num++;
 775   if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0;
 776   int result = jio_snprintf(current_file_name,  JVM_MAXPATHLEN,
 777                                 "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
 778   if (result >= JVM_MAXPATHLEN) {
 779     warning("Cannot create new log file name: %s: file name is too long.\n",
 780                                                              current_file_name);
 781     return;
 782   }
 783 
 784   _file = fopen(current_file_name, "w");
 785 
 786   if (_file != NULL) {
 787     _bytes_written = 0L;
 788     _need_close = true;
 789     // reuse current_file_name for time_msg
 790     jio_snprintf(current_file_name, JVM_MAXPATHLEN,
 791                  "%s.%d", _file_name, _cur_file_num);
 792     jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
 793                            os::local_time_string((char *)time_str, sizeof(time_str)),
 794                            current_file_name);
 795     write(time_msg, strlen(time_msg));
 796 
 797     if (out != NULL) {
 798       out->print("%s", time_msg);
 799     }
 800 
 801     dump_loggc_header();
 802     // remove the existing file
 803     if (access(current_file_name, F_OK) == 0) {
 804       if (remove(current_file_name) != 0) {
 805         warning("Could not delete existing file %s\n", current_file_name);
 806       }
 807     }
 808   } else {
 809     warning("failed to open rotation log file %s due to %s\n"
 810             "Turned off GC log file rotation\n",