docs: def doRollover(self):
          """
          Do a rollover, as described in __init__().
          """
          self._close()
          if self.backupCount <= 0:
              # Don't keep any backups, just overwrite the existing backup file
              # Locking doesn't much matter here; since we are overwriting it anyway
              self.stream = self.do_open("w")
              self._close()
              return
  
          # Determine if we can rename the log file or not. Windows refuses to
          # rename an open file, Unix is inode base so it doesn't care.
  
          # Attempt to rename logfile to tempname:
          # There is a slight race-condition here, but it seems unavoidable
          tmpname = None
          while not tmpname or os.path.exists(tmpname):
              tmpname = "%s.rotate.%08d" % (self.baseFilename, randbits(64))
          try:
              # Do a rename test to determine if we can successfully rename the log file
              os.rename(self.baseFilename, tmpname)
  
              if self.use_gzip:
                  self.do_gzip(tmpname)
          except (IOError, OSError):
              exc_value = sys.exc_info()[1]
              self._console_log(
                  "rename failed.  File in use? exception=%s" % (exc_value,), stack=True)
              return
  
          gzip_ext = ''
          if self.use_gzip:
              gzip_ext = '.gz'
  
          def do_rename(source_fn, dest_fn):
              self._console_log("Rename %s -> %s" % (source_fn, dest_fn + gzip_ext))
              if os.path.exists(dest_fn):
                  os.remove(dest_fn)
              if os.path.exists(dest_fn + gzip_ext):
                  os.remove(dest_fn + gzip_ext)
              source_gzip = source_fn + gzip_ext
              if os.path.exists(source_gzip):
                  os.rename(source_gzip, dest_fn + gzip_ext)
              elif os.path.exists(source_fn):
                  os.rename(source_fn, dest_fn)
  
          # Q: Is there some way to protect this code from a KeyboardInterrupt?
          # This isn't necessarily a data loss issue, but it certainly does
          # break the rotation process during stress testing.
  
          # There is currently no mechanism in place to handle the situation
          # where one of these log files cannot be renamed. (Example, user
          # opens "logfile.3" in notepad); we could test rename each file, but
          # nobody's complained about this being an issue; so the additional
          # code complexity isn't warranted.
          for i in range(self.backupCount - 1, 0, -1):
              sfn = "%s.%d" % (self.baseFilename, i)
              dfn = "%s.%d" % (self.baseFilename, i + 1)
              if os.path.exists(sfn + gzip_ext):
                  do_rename(sfn, dfn)
          dfn = self.baseFilename + ".1"
          do_rename(tmpname, dfn)
  
          if self.use_gzip:
              logFilename = self.baseFilename + ".1.gz"
              self._do_chown_and_chmod(logFilename)
  
          self._console_log("Rotation completed")