docs: private synchronized PrintStream getPrintStream(long numNewChars) {
          switch (currentStatus) {
              case INIT:
  
                  if (!newLogsOnStart) {
  
                      // Check if we can fill into an existing file (including a new log header).
                      File primaryFile = getPrimaryFile();
                      if (primaryFile.exists()) {
  
                          // If maxFileSize is set in bootstrap.properties, then maxFileSizeBytes will have been
                          // updated before this INIT check to that value; otherwise, if maxFileSize was not
                          // set (i.e. default) or it was set in server.xml, then config processing hasn't run
                          // yet, so maxFileSizeBytes will be 0 (there will be an `update` call later). In the
                          // latter case, this means that we might add the logging header (about 1KB) plus
                          // any other messages up until that size update, meaning that we could go
                          // over the configured maxFileSize by a little bit, but this is okay. In that case,
                          // maxFileSizeBytes will be 0, so we'll fill the existing file, and then later on,
                          // it'll roll over if needed.
  
                          if (maxFileSizeBytes <= 0 || primaryFile.length() + logHeader.length() + numNewChars <= maxFileSizeBytes) {
                              // There's space, so print the header and return the stream.
  
                              return getPrimaryStream(true);
                          }
                      }
                  }
  
                  return createStream(true);
              case ACTIVE:
                  if (maxFileSizeBytes > 0) {
                      long bytesWritten = currentCountingStream.count();
  
                      // Replace the stream if the size is or will likely be
                      // exceeded.  We're estimating one byte per char, which is
                      // only accurate for single-byte character sets.  That's
                      // fine: if a multi-byte character set is being used and
                      // we underestimate the number of bytes that will be
                      // written, we'll roll the log next time.
                      if (bytesWritten + numNewChars > maxFileSizeBytes)
                          return createStream(true);
                  }
                  break;
              case CLOSED:
                  if (checkTime == null) {
                      checkTime = Long.valueOf(Calendar.getInstance().getTimeInMillis());
                  } else {
                      long currentTime = Calendar.getInstance().getTimeInMillis();
                      // try to create stream again for every 5 seconds
                      if (currentTime - checkTime.longValue() > 5000L) {
                          checkTime = Long.valueOf(currentTime);
                          // show error for every 10 minutes
                          boolean showError = (retryTime == null) || (currentTime - retryTime.longValue() > 600000L);
                          if (showError)
                              retryTime = Long.valueOf(currentTime);
                          PrintStream ps = createStream(showError);
                          if (this.currentStatus == StreamStatus.ACTIVE) {
                              // stream successfully created
                              Tr.audit(getTc(), "LOG_FILE_RESUMED", new Object[] { getPrimaryFile().getAbsolutePath() });
                              this.checkTime = null;
                              this.retryTime = null;
                          }
                          return ps;
                      }
                  }
          }
  
          return currentPrintStream;
      }