From 5e58f0a0ebfcf523fa1bd7cc74e3808140c75261 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 20 Feb 2012 12:33:57 -0500 Subject: [PATCH] Workaround 1 sec resolution of File.lastModified on Linux (issue-55) Shockingly, File.lastModified() does not always support millisecond resolution on all platforms even if the underlying filesystem supports it. Added a forceReload flag (in addition to last modified checks) to ensure that user backends and configuration properties are properly reloaded. --- src/com/gitblit/ConfigUserService.java | 8 +++++++- src/com/gitblit/FileSettings.java | 15 ++++++++++++++- src/com/gitblit/FileUserService.java | 3 ++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/com/gitblit/ConfigUserService.java b/src/com/gitblit/ConfigUserService.java index 681efd53..8f47f7a0 100644 --- a/src/com/gitblit/ConfigUserService.java +++ b/src/com/gitblit/ConfigUserService.java @@ -82,6 +82,8 @@ public class ConfigUserService implements IUserService { private final Map teams = new ConcurrentHashMap(); private volatile long lastModified; + + private volatile boolean forceReload; public ConfigUserService(File realmFile) { this.realmFile = realmFile; @@ -711,6 +713,9 @@ public class ConfigUserService implements IUserService { } config.save(); + // manually set the forceReload flag because not all JVMs support real + // millisecond resolution of lastModified. (issue-55) + forceReload = true; // If the write is successful, delete the current file and rename // the temporary copy to the original filename. @@ -735,7 +740,8 @@ public class ConfigUserService implements IUserService { * Reads the realm file and rebuilds the in-memory lookup tables. */ protected synchronized void read() { - if (realmFile.exists() && (realmFile.lastModified() > lastModified)) { + if (realmFile.exists() && (forceReload || (realmFile.lastModified() != lastModified))) { + forceReload = false; lastModified = realmFile.lastModified(); users.clear(); cookies.clear(); diff --git a/src/com/gitblit/FileSettings.java b/src/com/gitblit/FileSettings.java index 8ac99f6d..666bda05 100644 --- a/src/com/gitblit/FileSettings.java +++ b/src/com/gitblit/FileSettings.java @@ -37,6 +37,8 @@ public class FileSettings extends IStoredSettings { private final Properties properties = new Properties(); private volatile long lastModified; + + private volatile boolean forceReload; public FileSettings(String file) { super(FileSettings.class); @@ -49,7 +51,7 @@ public class FileSettings extends IStoredSettings { */ @Override protected synchronized Properties read() { - if (propertiesFile.exists() && (propertiesFile.lastModified() > lastModified)) { + if (propertiesFile.exists() && (forceReload || (propertiesFile.lastModified() > lastModified))) { FileInputStream is = null; try { Properties props = new Properties(); @@ -60,6 +62,7 @@ public class FileSettings extends IStoredSettings { properties.clear(); properties.putAll(props); lastModified = propertiesFile.lastModified(); + forceReload = false; } catch (FileNotFoundException f) { // IGNORE - won't happen because file.exists() check above } catch (Throwable t) { @@ -88,6 +91,9 @@ public class FileSettings extends IStoredSettings { content = content.replaceAll(regex, setting.getKey() + " = " + setting.getValue()); } FileUtils.writeContent(propertiesFile, content); + // manually set the forceReload flag because not all JVMs support real + // millisecond resolution of lastModified. (issue-55) + forceReload = true; return true; } @@ -102,6 +108,13 @@ public class FileSettings extends IStoredSettings { return lastModified; } + /** + * @return the state of the force reload flag + */ + protected boolean forceReload() { + return forceReload; + } + @Override public String toString() { return propertiesFile.getAbsolutePath(); diff --git a/src/com/gitblit/FileUserService.java b/src/com/gitblit/FileUserService.java index dfc4da8a..7842c31d 100644 --- a/src/com/gitblit/FileUserService.java +++ b/src/com/gitblit/FileUserService.java @@ -624,8 +624,9 @@ public class FileUserService extends FileSettings implements IUserService { @Override protected synchronized Properties read() { long lastRead = lastModified(); + boolean reload = forceReload(); Properties allUsers = super.read(); - if (lastRead != lastModified()) { + if (reload || (lastRead != lastModified())) { // reload hash cache cookies.clear(); teams.clear(); -- 2.39.5