Option to disable timestamps during scan

I accidentally deleted most of my music directory. The database was
still intact. I recovered the music directory by rolling back to a
previous ZFS snapshot and performed a reindex. However, libresonic did
not mark the deleted files as present. Turns out the file timestamp was
unchanged through the ZFS restore, and so libresonic still thought the
last indexing effort was still "good".

This adds the option to ignore file timestamps when scanning files. This
can be helpful in the case of a restore as described above. There might
be a better way to do this, as this was really a quick effort on my part
to fix my own libresonic.

This does not add a UI, just a single property that can be turned on by
editing the lilbresonic.properties file.

@fxthomas suggested this could instead be a query parameter on the
initial issue #359. That would basically move the potential UI to the
scan page. That would be fine, but I could imagine there might be cases
where people want this setting on all the time.

Signed-off-by: Andrew DeMaria <lostonamountain@gmail.com>
master
Andrew DeMaria 7 years ago
parent 41967e76df
commit 45d789b64e
No known key found for this signature in database
GPG Key ID: 0A3F5E91F8364EDF
  1. 6
      airsonic-main/src/main/java/org/airsonic/player/dao/AlbumDao.java
  2. 8
      airsonic-main/src/main/java/org/airsonic/player/dao/ArtistDao.java
  3. 9
      airsonic-main/src/main/java/org/airsonic/player/dao/MediaFileDao.java
  4. 6
      airsonic-main/src/main/java/org/airsonic/player/service/MediaFileService.java
  5. 10
      airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java

@ -334,12 +334,12 @@ public class AlbumDao extends AbstractDao {
}
public void markNonPresent(Date lastScanned) {
int minId = queryForInt("select min(id) from album where last_scanned != ? and present", 0, lastScanned);
int maxId = queryForInt("select max(id) from album where last_scanned != ? and present", 0, lastScanned);
int minId = queryForInt("select min(id) from album where last_scanned < ? and present", 0, lastScanned);
int maxId = queryForInt("select max(id) from album where last_scanned < ? and present", 0, lastScanned);
final int batchSize = 1000;
for (int id = minId; id <= maxId; id += batchSize) {
update("update album set present=false where id between ? and ? and last_scanned != ? and present", id, id + batchSize, lastScanned);
update("update album set present=false where id between ? and ? and last_scanned < ? and present", id, id + batchSize, lastScanned);
}
}

@ -156,16 +156,16 @@ public class ArtistDao extends AbstractDao {
}
public void markPresent(String artistName, Date lastScanned) {
update("update artist set present=?, last_scanned=? where name=?", true, lastScanned, artistName);
update("update artist set present=?, last_scanned = ? where name=?", true, lastScanned, artistName);
}
public void markNonPresent(Date lastScanned) {
int minId = queryForInt("select min(id) from artist where last_scanned != ? and present", 0, lastScanned);
int maxId = queryForInt("select max(id) from artist where last_scanned != ? and present", 0, lastScanned);
int minId = queryForInt("select min(id) from artist where last_scanned < ? and present", 0, lastScanned);
int maxId = queryForInt("select max(id) from artist where last_scanned < ? and present", 0, lastScanned);
final int batchSize = 1000;
for (int id = minId; id <= maxId; id += batchSize) {
update("update artist set present=false where id between ? and ? and last_scanned != ? and present", id, id + batchSize, lastScanned);
update("update artist set present=false where id between ? and ? and last_scanned < ? and present", id, id + batchSize, lastScanned);
}
}

@ -646,17 +646,18 @@ public class MediaFileDao extends AbstractDao {
}
public void markPresent(String path, Date lastScanned) {
update("update media_file set present=?, last_scanned=? where path=?", true, lastScanned, path);
update("update media_file set present=?, last_scanned = ? where path=?", true, lastScanned, path);
}
public void markNonPresent(Date lastScanned) {
int minId = queryForInt("select min(id) from media_file where last_scanned != ? and present", 0, lastScanned);
int maxId = queryForInt("select max(id) from media_file where last_scanned != ? and present", 0, lastScanned);
int minId = queryForInt("select min(id) from media_file where last_scanned < ? and present", 0, lastScanned);
int maxId = queryForInt("select max(id) from media_file where last_scanned < ? and present", 0, lastScanned);
final int batchSize = 1000;
Date childrenLastUpdated = new Date(0L); // Used to force a children rescan if file is later resurrected.
for (int id = minId; id <= maxId; id += batchSize) {
update("update media_file set present=false, children_last_updated=? where id between ? and ? and last_scanned != ? and present",
update("update media_file set present=false, children_last_updated=? where id between ? and ? and " +
"last_scanned < ? and present",
childrenLastUpdated, id, id + batchSize, lastScanned);
}
}

@ -151,9 +151,13 @@ public class MediaFileService {
}
private MediaFile checkLastModified(MediaFile mediaFile, boolean useFastCache) {
if (useFastCache || (mediaFile.getVersion() >= MediaFileDao.VERSION && mediaFile.getChanged().getTime() >= FileUtil.lastModified(mediaFile.getFile()))) {
if (useFastCache || (mediaFile.getVersion() >= MediaFileDao.VERSION
&& !settingsService.isIgnoreFileTimestamps()
&& mediaFile.getChanged().getTime() >= FileUtil.lastModified(mediaFile.getFile()))) {
LOG.debug("Detected unmodified file");
return mediaFile;
}
LOG.debug("Updating database file from disk");
mediaFile = createMediaFile(mediaFile.getFile());
mediaFileDao.createOrUpdateMediaFile(mediaFile);
return mediaFile;

@ -77,6 +77,7 @@ public class SettingsService {
private static final String KEY_INDEX_CREATION_INTERVAL = "IndexCreationInterval";
private static final String KEY_INDEX_CREATION_HOUR = "IndexCreationHour";
private static final String KEY_FAST_CACHE_ENABLED = "FastCacheEnabled";
private static final String KEY_IGNORE_FILE_TIMESTAMPS = "IgnoreFileTimestamps";
private static final String KEY_PODCAST_UPDATE_INTERVAL = "PodcastUpdateInterval";
private static final String KEY_PODCAST_FOLDER = "PodcastFolder";
private static final String KEY_PODCAST_EPISODE_RETENTION_COUNT = "PodcastEpisodeRetentionCount";
@ -160,6 +161,7 @@ public class SettingsService {
private static final int DEFAULT_INDEX_CREATION_INTERVAL = 1;
private static final int DEFAULT_INDEX_CREATION_HOUR = 3;
private static final boolean DEFAULT_FAST_CACHE_ENABLED = false;
private static final boolean DEFAULT_IGNORE_FILE_TIMESTAMPS = false;
private static final int DEFAULT_PODCAST_UPDATE_INTERVAL = 24;
private static final String DEFAULT_PODCAST_FOLDER = Util.getDefaultPodcastFolder();
private static final int DEFAULT_PODCAST_EPISODE_RETENTION_COUNT = 10;
@ -537,6 +539,14 @@ public class SettingsService {
setBoolean(KEY_FAST_CACHE_ENABLED, enabled);
}
public boolean isIgnoreFileTimestamps() {
return getBoolean(KEY_IGNORE_FILE_TIMESTAMPS, DEFAULT_IGNORE_FILE_TIMESTAMPS);
}
public void setIgnoreFileTimestamps(boolean ignore) {
setBoolean(KEY_IGNORE_FILE_TIMESTAMPS, ignore);
}
/**
* Returns the number of hours between Podcast updates, of -1 if automatic updates
* are disabled.

Loading…
Cancel
Save