63
63
import java .io .IOException ;
64
64
import java .util .ArrayList ;
65
65
import java .util .Collections ;
66
+ import java .util .HashMap ;
66
67
import java .util .Iterator ;
67
68
import java .util .List ;
68
69
import java .util .Map ;
@@ -154,23 +155,37 @@ public void clear(Index index, String field) {
154
155
fieldsOfIndex .add (field );
155
156
}
156
157
157
- // This method can stay synchronized to avoid having multiple simultaneous cache iterators removing keys.
158
- // This shouldn't cause performance impact as it's called only from the scheduled cache clear thread
159
- // and is not blocking search traffic.
160
- public void clearMarkedKeys () {
158
+ // The synchronized block is to avoid having multiple simultaneous cache iterators removing keys.
159
+ public void clear () {
161
160
if (!(indicesToClear .isEmpty () && fieldsToClear .isEmpty ())) {
161
+ // Copy marked indices/fields before iteration, and only remove keys matching the copies
162
+ // in case new entries are marked for cleanup mid-iteration
163
+ Set <Index > indicesToClearCopy = Set .copyOf (indicesToClear );
164
+ Map <Index , Set <String >> fieldsToClearCopy = new HashMap <>();
165
+ for (Map .Entry <Index , Set <String >> entry : fieldsToClear .entrySet ()) {
166
+ fieldsToClearCopy .put (entry .getKey (), Set .copyOf (entry .getValue ()));
167
+ }
168
+ // remove this way instead of clearing all, in case a new entry has been marked since copying
169
+ indicesToClear .removeAll (indicesToClearCopy );
170
+ for (Map .Entry <Index , Set <String >> entry : fieldsToClearCopy .entrySet ()) {
171
+ Set <String > fieldsForIndex = fieldsToClear .get (entry .getKey ());
172
+ if (fieldsForIndex != null ) {
173
+ fieldsForIndex .removeAll (entry .getValue ());
174
+ }
175
+ }
176
+
162
177
synchronized (this ) {
163
178
for (Iterator <Key > iterator = getCache ().keys ().iterator (); iterator .hasNext ();) {
164
179
Key key = iterator .next ();
165
- if (indicesToClear .contains (key .indexCache .index )) {
180
+ if (indicesToClearCopy .contains (key .indexCache .index )) {
166
181
try {
167
182
iterator .remove ();
168
183
} catch (Exception e ) {
169
184
logger .warn ("Exception occurred while removing key from cache" , e );
170
185
}
171
186
continue ;
172
187
}
173
- Set <String > fieldsOfIndexToClear = fieldsToClear .get (key .indexCache .index );
188
+ Set <String > fieldsOfIndexToClear = fieldsToClearCopy .get (key .indexCache .index );
174
189
if (fieldsOfIndexToClear != null && fieldsOfIndexToClear .contains (key .indexCache .fieldName )) {
175
190
try {
176
191
iterator .remove ();
@@ -180,8 +195,6 @@ public void clearMarkedKeys() {
180
195
}
181
196
}
182
197
}
183
- indicesToClear .clear ();
184
- fieldsToClear .clear ();
185
198
}
186
199
cache .refresh ();
187
200
}
0 commit comments