16
16
import org .elasticsearch .reservedstate .service .FileChangedListener ;
17
17
18
18
import java .io .IOException ;
19
+ import java .io .InputStream ;
19
20
import java .nio .file .ClosedWatchServiceException ;
20
- import java .nio .file .Files ;
21
21
import java .nio .file .Path ;
22
22
import java .nio .file .StandardWatchEventKinds ;
23
23
import java .nio .file .WatchKey ;
24
24
import java .nio .file .WatchService ;
25
25
import java .nio .file .attribute .BasicFileAttributes ;
26
+ import java .nio .file .attribute .FileTime ;
26
27
import java .util .List ;
27
28
import java .util .concurrent .CopyOnWriteArrayList ;
28
29
import java .util .concurrent .ExecutionException ;
30
+ import java .util .stream .Stream ;
29
31
30
32
/**
31
33
* A skeleton service for watching and reacting to a single file changing on disk
@@ -119,20 +121,20 @@ public final boolean watching() {
119
121
// platform independent way to tell if a file changed
120
122
// we compare the file modified timestamp, the absolute path (symlinks), and file id on the system
121
123
final boolean watchedFileChanged (Path path ) throws IOException {
122
- if (Files . exists (path ) == false ) {
124
+ if (filesExists (path ) == false ) {
123
125
return false ;
124
126
}
125
127
126
128
FileUpdateState previousUpdateState = fileUpdateState ;
127
129
128
- BasicFileAttributes attr = Files . readAttributes (path , BasicFileAttributes .class );
130
+ BasicFileAttributes attr = filesReadAttributes (path , BasicFileAttributes .class );
129
131
fileUpdateState = new FileUpdateState (attr .lastModifiedTime ().toMillis (), path .toRealPath ().toString (), attr .fileKey ());
130
132
131
133
return (previousUpdateState == null || previousUpdateState .equals (fileUpdateState ) == false );
132
134
}
133
135
134
136
protected final synchronized void startWatcher () {
135
- if (Files . exists (watchedFileDir .getParent ()) == false ) {
137
+ if (filesExists (watchedFileDir .getParent ()) == false ) {
136
138
logger .warn ("File watcher for [{}] cannot start because grandparent directory does not exist" , watchedFile );
137
139
return ;
138
140
}
@@ -147,7 +149,7 @@ protected final synchronized void startWatcher() {
147
149
try {
148
150
Path settingsDirPath = watchedFileDir ();
149
151
this .watchService = settingsDirPath .getParent ().getFileSystem ().newWatchService ();
150
- if (Files . exists (settingsDirPath )) {
152
+ if (filesExists (settingsDirPath )) {
151
153
settingsDirWatchKey = enableDirectoryWatcher (settingsDirWatchKey , settingsDirPath );
152
154
} else {
153
155
logger .debug ("watched directory [{}] not found, will watch for its creation..." , settingsDirPath );
@@ -181,7 +183,7 @@ protected final void watcherThread() {
181
183
182
184
Path path = watchedFile ();
183
185
184
- if (Files . exists (path )) {
186
+ if (filesExists (path )) {
185
187
logger .debug ("found initial operator settings file [{}], applying..." , path );
186
188
processSettingsOnServiceStartAndNotifyListeners ();
187
189
} else {
@@ -209,7 +211,7 @@ protected final void watcherThread() {
209
211
* real path of our desired file. We don't actually care what changed, we just re-check ourselves.
210
212
*/
211
213
Path settingsPath = watchedFileDir ();
212
- if (Files . exists (settingsPath )) {
214
+ if (filesExists (settingsPath )) {
213
215
try {
214
216
if (logger .isDebugEnabled ()) {
215
217
key .pollEvents ().forEach (e -> logger .debug ("{}:{}" , e .kind ().toString (), e .context ().toString ()));
@@ -332,4 +334,19 @@ long retryDelayMillis(int failedCount) {
332
334
* class to determine if a file has been changed.
333
335
*/
334
336
private record FileUpdateState (long timestamp , String path , Object fileKey ) {}
337
+
338
+ // the following methods are a workaround to ensure exclusive access for files
339
+ // required by child watchers; this is required because we only check the caller's module
340
+ // not the entire stack
341
+ protected abstract boolean filesExists (Path path );
342
+
343
+ protected abstract boolean filesIsDirectory (Path path );
344
+
345
+ protected abstract <A extends BasicFileAttributes > A filesReadAttributes (Path path , Class <A > clazz ) throws IOException ;
346
+
347
+ protected abstract Stream <Path > filesList (Path dir ) throws IOException ;
348
+
349
+ protected abstract Path filesSetLastModifiedTime (Path path , FileTime time ) throws IOException ;
350
+
351
+ protected abstract InputStream filesNewInputStream (Path path ) throws IOException ;
335
352
}
0 commit comments