/** * This method assumes that both files a and b exists. * * @param a * @param b * @return * @throws Exception */ static public boolean areOnSameFileStore(File a, File b) throws RolloverFailure { if (!a.exists()) { throw new IllegalArgumentException("File [" + a + "] does not exist."); } if (!b.exists()) { throw new IllegalArgumentException("File [" + b + "] does not exist."); } // Implements the following by reflection // Path pathA = a.toPath(); // Path pathB = b.toPath(); // // FileStore fileStoreA = Files.getFileStore(pathA); // FileStore fileStoreB = Files.getFileStore(pathB); // // return fileStoreA.equals(fileStoreB); try { Class<?> pathClass = Class.forName(PATH_CLASS_STR); Class<?> filesClass = Class.forName(FILES_CLASS_STR); Method toPath = File.class.getMethod("toPath"); Method getFileStoreMethod = filesClass.getMethod("getFileStore", pathClass); Object pathA = toPath.invoke(a); Object pathB = toPath.invoke(b); Object fileStoreA = getFileStoreMethod.invoke(null, pathA); Object fileStoreB = getFileStoreMethod.invoke(null, pathB); return fileStoreA.equals(fileStoreB); } catch (Exception e) { throw new RolloverFailure("Failed to check file store equality for [" + a + "] and [" + b + "]", e); } }
/** * A relatively robust file renaming method which in case of failure due to * src and target being on different volumes, falls back onto * renaming by copying. * * @param src * @param target * @throws RolloverFailure */ public void rename(String src, String target) throws RolloverFailure { if (src.equals(target)) { addWarn("Source and target files are the same [" + src + "]. Skipping."); return; } File srcFile = new File(src); if (srcFile.exists()) { File targetFile = new File(target); createMissingTargetDirsIfNecessary(targetFile); addInfo("Renaming file [" + srcFile + "] to [" + targetFile + "]"); boolean result = srcFile.renameTo(targetFile); if (!result) { addWarn("Failed to rename file [" + srcFile + "] as [" + targetFile + "]."); if (areOnDifferentVolumes(srcFile, targetFile)) { addWarn("Detected different file systems for source [" + src + "] and target [" + target + "]. Attempting rename by copying."); renameByCopying(src, target); return; } else { addWarn("Please consider leaving the [file] option of " + RollingFileAppender.class.getSimpleName() + " empty."); addWarn("See also " + RENAMING_ERROR_URL); } } } else { throw new RolloverFailure("File [" + src + "] does not exist."); } }
/** * Attempts tp determine whether both files are on different volumes. Returns true if we could determine that * the files are on different volumes. Returns false otherwise or if an error occurred while doing the check. * * @param srcFile * @param targetFile * @return true if on different volumes, false otherwise or if an error occurred */ boolean areOnDifferentVolumes(File srcFile, File targetFile) throws RolloverFailure { if (!EnvUtil.isJDK7OrHigher()) return false; File parentOfTarget = targetFile.getParentFile(); try { boolean onSameFileStore = FileStoreUtil.areOnSameFileStore(srcFile, parentOfTarget); return !onSameFileStore; } catch (RolloverFailure rf) { addWarn("Error while checking file store equality", rf); return false; } }
public void renameByCopying(String src, String target) throws RolloverFailure { FileUtil fileUtil = new FileUtil(getContext()); fileUtil.copy(src, target); File srcFile = new File(src); if (!srcFile.delete()) { addWarn("Could not delete " + src); } }
void createMissingTargetDirsIfNecessary(File toFile) throws RolloverFailure { boolean result = FileUtil.createMissingParentDirectories(toFile); if (!result) { throw new RolloverFailure("Failed to create parent directories for [" + toFile.getAbsolutePath() + "]"); } }
@Test public void filesOnSameFolderShouldBeOnTheSameFileStore() throws RolloverFailure, IOException { if(!EnvUtil.isJDK7OrHigher()) return; File parent = new File(pathPrefix); File file = new File(pathPrefix+"filesOnSameFolderShouldBeOnTheSameFileStore"); FileUtil.createMissingParentDirectories(file); file.createNewFile(); assertTrue(FileStoreUtil.areOnSameFileStore(parent, file)); }
@Ignore @Test public void manual_filesOnDifferentVolumesShouldBeDetectedAsSuch() throws RolloverFailure { if(!EnvUtil.isJDK7OrHigher()) return; // author's computer has two volumes File c = new File("c:/tmp/"); File d = new File("d:/"); assertFalse(FileStoreUtil.areOnSameFileStore(c, d)); }
/** * Rollover current log file name, after we append the rollover time to it (so we can know the time each file * covers * * @throws RolloverFailure */ @Override public void rollover() throws RolloverFailure { //Get last active file name (to rename it) String prevActiveFileName = getActiveFileName(); //Keep last start date, since we update it now long previousStarted = startedTime; startedTime = System.currentTimeMillis(); //Rename append start and end time to the last active file name util.rename(prevActiveFileName, activeLogFilePath + "." + previousStarted + TS_SEP + startedTime + LOG_EXT); }
@Override public void start() { super.start(); nextCheck = 0L; isTriggeringEvent(null, null); try { tbrp.rollover(); } catch (RolloverFailure e) { // Do nothing } }
@Override public void rollover() throws RolloverFailure { // noop }
@Override public void rollover() throws RolloverFailure {}