/** Create or open log files used by this log. */ private void createOrOpenLogFiles() throws ChangelogException { exclusiveLock.lock(); try { createRootDirIfNotExists(); openHeadLogFile(); for (final File file : getReadOnlyLogFiles()) { openReadOnlyLogFile(file); } isClosed = false; } catch (ChangelogException e) { // ensure all log files opened at this point are closed close(); throw new ChangelogException( ERR_CHANGELOG_UNABLE_TO_INITIALIZE_LOG.get(logPath.getPath()), e); } finally { exclusiveLock.unlock(); } }
/** * 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(); }
/** * Empties the log, discarding all records it contains. * * <p>All cursors open on the log are aborted. * * @throws ChangelogException If cursors are opened on this log, or if a problem occurs during * clearing operation. */ public void clear() throws ChangelogException { exclusiveLock.lock(); try { if (isClosed) { return; } if (!openCursors.isEmpty()) { // All open cursors are aborted, which means the change number indexer thread // should manage AbortedChangelogCursorException specifically to avoid being // stopped abortAllOpenCursors(); } // delete all log files final List<String> undeletableFiles = new ArrayList<>(); for (LogFile<K, V> logFile : logFiles.values()) { try { logFile.close(); logFile.delete(); } catch (ChangelogException e) { undeletableFiles.add(logFile.getFile().getPath()); } } if (!undeletableFiles.isEmpty()) { throw new ChangelogException( ERR_CHANGELOG_UNABLE_TO_DELETE_LOG_FILE.get( Utils.joinAsString(", ", undeletableFiles))); } logFiles.clear(); // recreate an empty head log file openHeadLogFile(); } catch (Exception e) { throw new ChangelogException( ERR_ERROR_CLEARING_DB.get(logPath.getPath(), stackTraceToSingleLineString(e))); } finally { exclusiveLock.unlock(); } }