/** * Rotate the head log file to a read-only log file, and open a new empty head log file to write * in. * * <p>All cursors opened on this log are temporarily disabled (closing underlying resources) and * then re-open with their previous state. */ private void rotateHeadLogFile() throws ChangelogException { // Temporarily disable cursors opened on head, saving their state final List<Pair<AbortableLogCursor<K, V>, CursorState<K, V>>> cursorsOnHead = disableOpenedCursorsOnHead(); final LogFile<K, V> headLogFile = getHeadLogFile(); final File readOnlyLogFile = new File(logPath, generateReadOnlyFileName(headLogFile)); headLogFile.close(); renameHeadLogFileTo(readOnlyLogFile); openHeadLogFile(); openReadOnlyLogFile(readOnlyLogFile); // Re-enable cursors previously opened on head, with the saved state updateOpenedCursorsOnHeadAfterRotation(cursorsOnHead); // Notify even if time-based rotation is not enabled, as it could be enabled at any time replicationEnv.notifyLogFileRotation(this); lastRotationTime = timeService.now(); }
private boolean mustRotate(LogFile<K, V> headLogFile) { if (lastAppendedKey == null) { // never rotate an empty file return false; } if (headLogFile.getSizeInBytes() > sizeLimitPerLogFileInBytes) { // rotate because file size exceeded threshold logger.trace( "Rotate log %s due to size: %s", logPath.getPath(), headLogFile.getSizeInBytes()); return true; } if (rotationIntervalInMillis > 0) { // rotate if time limit is reached final long timeElapsed = timeService.since(lastRotationTime); boolean shouldRotate = timeElapsed > rotationIntervalInMillis; if (shouldRotate) { logger.trace( "Rotate log %s due to time: time elapsed %s, rotation interval: %s", logPath.getPath(), timeElapsed, rotationIntervalInMillis); } return shouldRotate; } return false; }