/** * Returns the file name to use for the read-only version of the provided log file. * * <p>The file name is based on the lowest and highest key in the log file. * * @return the name to use for the read-only version of the log file * @throws ChangelogException If an error occurs. */ private String generateReadOnlyFileName(final LogFile<K, V> logFile) throws ChangelogException { final K lowestKey = logFile.getOldestRecord().getKey(); final K highestKey = logFile.getNewestRecord().getKey(); return recordParser.encodeKeyToString(lowestKey) + LOG_FILE_NAME_SEPARATOR + recordParser.encodeKeyToString(highestKey) + LOG_FILE_SUFFIX; }
/** * Returns the key bounds for the provided log file. * * @return the pair of (lowest key, highest key) that correspond to records stored in the * corresponding log file. * @throws ChangelogException if an error occurs while retrieving the keys */ private Pair<K, K> getKeyBounds(final LogFile<K, V> logFile) throws ChangelogException { try { final String name = logFile.getFile().getName(); final String[] keys = name.substring(0, name.length() - Log.LOG_FILE_SUFFIX.length()) .split(LOG_FILE_NAME_SEPARATOR); return Pair.of( recordParser.decodeKeyFromString(keys[0]), recordParser.decodeKeyFromString(keys[1])); } catch (Exception e) { throw new ChangelogException( ERR_CHANGELOG_UNABLE_TO_RETRIEVE_KEY_BOUNDS_FROM_FILE.get(logFile.getFile().getPath()), e); } }
private void openHeadLogFile() throws ChangelogException { final LogFile<K, V> head = LogFile.newAppendableLogFile(new File(logPath, HEAD_LOG_FILE_NAME), recordParser); final Record<K, V> newestRecord = head.getNewestRecord(); lastAppendedKey = newestRecord != null ? newestRecord.getKey() : null; logFiles.put(recordParser.getMaxKey(), head); }
/** Update the cursors that were pointing to head after a rotation of the head log file. */ private void updateOpenedCursorsOnHeadAfterRotation( List<Pair<AbortableLogCursor<K, V>, CursorState<K, V>>> cursors) throws ChangelogException { for (Pair<AbortableLogCursor<K, V>, CursorState<K, V>> pair : cursors) { final CursorState<K, V> cursorState = pair.getSecond(); // Need to update the cursor only if it is pointing to the head log file if (cursorState.isValid() && isHeadLogFile(cursorState.logFile)) { final K previousKey = logFiles.lowerKey(recordParser.getMaxKey()); final LogFile<K, V> logFile = findLogFileFor(previousKey); final AbortableLogCursor<K, V> cursor = pair.getFirst(); cursor.reinitializeTo( new CursorState<K, V>(logFile, cursorState.filePosition, cursorState.record)); } } }