public class FileSnapshot
extends java.lang.Object
This object tracks the last modified time of a file. Later during an
invocation of isModified(File)
the object will return true if the
file may have been modified and should be re-read from disk.
A snapshot does not "live update" when the underlying filesystem changes.
Callers must poll for updates by periodically invoking
isModified(File)
.
To work around the "racy git" problem (where a file may be modified multiple times within the granularity of the filesystem modification clock) this class may return true from isModified(File) if the last modification time of the file is less than 3 seconds ago.
Modifier and Type | Field and Description |
---|---|
private boolean |
cannotBeRacilyClean
True once
lastRead is far later than lastModified . |
private static java.time.format.DateTimeFormatter |
dateFmt |
private long |
delta |
static FileSnapshot |
DIRTY
A FileSnapshot that is considered to always be modified.
|
private java.io.File |
file |
private java.lang.Object |
fileKey
Object that uniquely identifies the given file, or
null if a file key is not available |
private boolean |
fileKeyChanged |
private FS.FileStoreAttributes |
fileStoreAttributeCache
measured FileStore attributes
|
private java.time.Instant |
lastModified
Last observed modification time of the path.
|
private boolean |
lastModifiedChanged |
private java.time.Instant |
lastRead
Last wall-clock time the path was read.
|
private static org.slf4j.Logger |
LOG |
static FileSnapshot |
MISSING_FILE
A FileSnapshot that is clean if the file does not exist.
|
private static java.lang.Object |
MISSING_FILEKEY |
private long |
racyThreshold |
private long |
size
Underlying file-system size in bytes.
|
private boolean |
sizeChanged |
static long |
UNKNOWN_SIZE
An unknown file size.
|
private static java.time.Instant |
UNKNOWN_TIME |
private boolean |
wasRacyClean |
Modifier | Constructor and Description |
---|---|
protected |
FileSnapshot(java.io.File file)
Record a snapshot for a specific file path.
|
protected |
FileSnapshot(java.io.File file,
boolean useConfig)
Record a snapshot for a specific file path.
|
private |
FileSnapshot(java.time.Instant read,
java.time.Instant modified,
long size,
java.time.Duration fsTimestampResolution,
java.lang.Object fileKey) |
Modifier and Type | Method and Description |
---|---|
boolean |
equals(FileSnapshot other)
Compare two snapshots to see if they cache the same information.
|
boolean |
equals(java.lang.Object obj) |
private long |
getEffectiveRacyThreshold() |
private static java.lang.Object |
getFileKey(java.nio.file.attribute.BasicFileAttributes fileAttributes) |
int |
hashCode() |
private boolean |
isFileKeyChanged(java.lang.Object currFileKey) |
boolean |
isModified(java.io.File path)
Check if the path may have been modified since the snapshot was saved.
|
private boolean |
isModified(java.time.Instant currLastModified) |
private boolean |
isRacyClean(java.time.Instant read) |
private boolean |
isSizeChanged(long currSize) |
long |
lastDelta() |
long |
lastModified()
Deprecated.
use
lastModifiedInstant() instead |
java.time.Instant |
lastModifiedInstant()
Get time of last snapshot update
|
long |
lastRacyThreshold() |
static FileSnapshot |
save(java.io.File path)
Record a snapshot for a specific file path.
|
static FileSnapshot |
save(java.time.Instant modified)
Record a snapshot for a file for which the last modification time is
already known.
|
static FileSnapshot |
save(long modified)
Deprecated.
use
save(Instant) instead. |
static FileSnapshot |
saveNoConfig(java.io.File path)
Record a snapshot for a specific file path without using config file to
get filesystem timestamp resolution.
|
void |
setClean(FileSnapshot other)
Update this snapshot when the content hasn't changed.
|
long |
size() |
java.lang.String |
toString() |
void |
waitUntilNotRacy()
Wait until this snapshot's file can't be racy anymore
|
(package private) boolean |
wasFileKeyChanged() |
(package private) boolean |
wasLastModifiedChanged() |
(package private) boolean |
wasLastModifiedRacilyClean() |
(package private) boolean |
wasSizeChanged() |
private static final org.slf4j.Logger LOG
public static final long UNKNOWN_SIZE
private static final java.time.Instant UNKNOWN_TIME
private static final java.lang.Object MISSING_FILEKEY
private static final java.time.format.DateTimeFormatter dateFmt
public static final FileSnapshot DIRTY
This instance is useful for application code that wants to lazily read a
file, but only after isModified(File)
gets invoked. The returned
snapshot contains only invalid status information.
public static final FileSnapshot MISSING_FILE
This instance is useful if the application wants to consider a missing
file to be clean. isModified(File)
will return false if the file
path does not exist.
private final java.time.Instant lastModified
private volatile java.time.Instant lastRead
private boolean cannotBeRacilyClean
lastRead
is far later than lastModified
.private final long size
UNKNOWN_SIZE
the size is not considered for modification checks.private FS.FileStoreAttributes fileStoreAttributeCache
private final java.lang.Object fileKey
null
if a file key is not availableprivate final java.io.File file
private boolean sizeChanged
private boolean fileKeyChanged
private boolean lastModifiedChanged
private boolean wasRacyClean
private long delta
private long racyThreshold
protected FileSnapshot(java.io.File file)
This method should be invoked before the file is accessed.
file
- the path to remember meta data for. The path's current status
information is saved.protected FileSnapshot(java.io.File file, boolean useConfig)
This method should be invoked before the file is accessed.
file
- the path to remember meta data for. The path's current status
information is saved.useConfig
- if true
read filesystem time resolution from
configuration file otherwise use fallback resolutionpublic static FileSnapshot save(java.io.File path)
This method should be invoked before the file is accessed.
path
- the path to later remember. The path's current status
information is saved.public static FileSnapshot saveNoConfig(java.io.File path)
This method should be invoked before the file is accessed. It is used by FileBasedConfig to avoid endless recursion.
path
- the path to later remember. The path's current status
information is saved.private static java.lang.Object getFileKey(java.nio.file.attribute.BasicFileAttributes fileAttributes)
@Deprecated public static FileSnapshot save(long modified)
save(Instant)
instead.This method should be invoked before the file is accessed.
Note that this method cannot rely on measuring file timestamp resolution to avoid racy git issues caused by finite file timestamp resolution since it's unknown in which filesystem the file is located. Hence the worst case fallback for timestamp resolution is used.
modified
- the last modification time of the filepublic static FileSnapshot save(java.time.Instant modified)
This method should be invoked before the file is accessed.
Note that this method cannot rely on measuring file timestamp resolution to avoid racy git issues caused by finite file timestamp resolution since it's unknown in which filesystem the file is located. Hence the worst case fallback for timestamp resolution is used.
modified
- the last modification time of the file@Deprecated public long lastModified()
lastModifiedInstant()
insteadpublic java.time.Instant lastModifiedInstant()
public long size()
public boolean isModified(java.io.File path)
path
- the path the snapshot describes.public void setClean(FileSnapshot other)
If the caller gets true from isModified(File)
, re-reads the
content, discovers the content is identical, and
equals(FileSnapshot)
is true, it can use
setClean(FileSnapshot)
to make a future
isModified(File)
return false. The logic goes something like
this:
if (snapshot.isModified(path)) { FileSnapshot other = FileSnapshot.save(path); Content newContent = ...; if (oldContent.equals(newContent) && snapshot.equals(other)) snapshot.setClean(other); }
other
- the other snapshot.public void waitUntilNotRacy() throws java.lang.InterruptedException
java.lang.InterruptedException
- if sleep was interruptedpublic boolean equals(FileSnapshot other)
other
- the other snapshot.public boolean equals(java.lang.Object obj)
equals
in class java.lang.Object
public int hashCode()
hashCode
in class java.lang.Object
boolean wasSizeChanged()
true
if FileSnapshot.isModified(File) found the file size
changedboolean wasFileKeyChanged()
true
if FileSnapshot.isModified(File) found the file key
changedboolean wasLastModifiedChanged()
true
if FileSnapshot.isModified(File) found the file's
lastModified changedboolean wasLastModifiedRacilyClean()
true
if FileSnapshot.isModified(File) detected that
lastModified is racily cleanpublic long lastDelta()
public long lastRacyThreshold()
public java.lang.String toString()
toString
in class java.lang.Object
private boolean isRacyClean(java.time.Instant read)
private long getEffectiveRacyThreshold()
private boolean isModified(java.time.Instant currLastModified)
private boolean isFileKeyChanged(java.lang.Object currFileKey)
private boolean isSizeChanged(long currSize)