34
34
import java .util .Arrays ;
35
35
import java .util .Collection ;
36
36
import java .util .HashSet ;
37
+ import java .util .List ;
37
38
import java .util .Set ;
38
39
import java .util .stream .Collectors ;
40
+ import java .util .stream .Stream ;
41
+
42
+ import static org .apache .lucene .index .IndexFileNames .SEGMENTS ;
39
43
40
44
/**
41
45
* Composite Directory will contain both local and remote directory
@@ -74,12 +78,37 @@ public CompositeDirectory(Directory localDirectory, Directory remoteDirectory, F
74
78
);
75
79
}
76
80
81
+ /**
82
+ * Returns names of all files stored in local directory
83
+ * @throws IOException in case of I/O error
84
+ */
85
+ private String [] listLocalFiles () throws IOException {
86
+ ensureOpen ();
87
+ logger .trace ("Composite Directory[{}]: listLocalOnly() called" , this ::toString );
88
+ return localDirectory .listAll ();
89
+ }
90
+
91
+ /**
92
+ * Returns a list of names of all block files stored in the local directory for a given file,
93
+ * including the original file itself if present.
94
+ *
95
+ * @param fileName The name of the file to search for, along with its associated block files.
96
+ * @return A list of file names, including the original file (if present) and all its block files.
97
+ * @throws IOException in case of I/O error while listing files.
98
+ */
99
+ private List <String > listBlockFiles (String fileName ) throws IOException {
100
+ return Stream .of (listLocalFiles ())
101
+ .filter (file -> file .equals (fileName ) || file .startsWith (fileName + FileTypeUtils .BLOCK_FILE_IDENTIFIER ))
102
+ .collect (Collectors .toList ());
103
+ }
104
+
77
105
/**
78
106
* Returns names of all files stored in this directory in sorted order
79
107
* Does not include locally stored block files (having _block_ in their names) and files pending deletion
80
108
*
81
109
* @throws IOException in case of I/O error
82
110
*/
111
+ // TODO: https://github.com/opensearch-project/OpenSearch/issues/17527
83
112
@ Override
84
113
public String [] listAll () throws IOException {
85
114
ensureOpen ();
@@ -105,6 +134,7 @@ public String[] listAll() throws IOException {
105
134
* Currently deleting only from local directory as files from remote should not be deleted as that is taken care by garbage collection logic of remote directory
106
135
* @param name the name of an existing file.
107
136
* @throws IOException in case of I/O error
137
+ * @throws NoSuchFileException when file does not exist in the directory
108
138
*/
109
139
@ Override
110
140
public void deleteFile (String name ) throws IOException {
@@ -115,7 +145,21 @@ public void deleteFile(String name) throws IOException {
115
145
} else if (Arrays .asList (listAll ()).contains (name ) == false ) {
116
146
throw new NoSuchFileException ("File " + name + " not found in directory" );
117
147
} else {
118
- fileCache .remove (getFilePath (name ));
148
+ List <String > blockFiles = listBlockFiles (name );
149
+ if (blockFiles .isEmpty ()) {
150
+ // Remove this condition when this issue is addressed.
151
+ // TODO: https://github.com/opensearch-project/OpenSearch/issues/17526
152
+ logger .debug ("The file [{}] or its block files do not exist in local directory" , name );
153
+ } else {
154
+ for (String blockFile : blockFiles ) {
155
+ if (fileCache .get (getFilePath (blockFile )) == null ) {
156
+ logger .debug ("The file [{}] exists in local but not part of FileCache, deleting it from local" , blockFile );
157
+ localDirectory .deleteFile (blockFile );
158
+ } else {
159
+ fileCache .remove (getFilePath (blockFile ));
160
+ }
161
+ }
162
+ }
119
163
}
120
164
}
121
165
@@ -254,6 +298,15 @@ public IndexInput openInput(String name, IOContext context) throws IOException {
254
298
public void close () throws IOException {
255
299
ensureOpen ();
256
300
logger .trace ("Composite Directory[{}]: close() called" , this ::toString );
301
+ String [] localFiles = listLocalFiles ();
302
+ for (String localFile : localFiles ) {
303
+ // Delete segments_N file with ref count 1 created during index creation on replica shards
304
+ // TODO: https://github.com/opensearch-project/OpenSearch/issues/17534
305
+ if (localFile .startsWith (SEGMENTS )) {
306
+ fileCache .remove (getFilePath (localFile ));
307
+ }
308
+ }
309
+ fileCache .prune ();
257
310
localDirectory .close ();
258
311
}
259
312
0 commit comments