2121import java .util .Collection ;
2222import java .util .Collections ;
2323import java .util .HashMap ;
24+ import java .util .HashSet ;
2425import java .util .List ;
2526import java .util .Map ;
27+ import java .util .Set ;
2628import java .util .concurrent .locks .ReentrantReadWriteLock ;
2729import org .apache .ignite .IgniteCheckedException ;
2830import org .apache .ignite .IgniteLogger ;
@@ -115,6 +117,9 @@ public static void registerIO() {
115117 /** Exclusive lock for DDL operations. */
116118 private final ReentrantReadWriteLock ddlLock = new ReentrantReadWriteLock ();
117119
120+ /** Set of index names currently in initial population (null if none). */
121+ private @ Nullable Set <IndexName > fillingIdxs ;
122+
118123 /**
119124 * @param ctx Kernal context.
120125 */
@@ -211,15 +216,45 @@ public Index createIndexDynamically(
211216 IndexDefinition definition ,
212217 SchemaIndexCacheVisitor cacheVisitor
213218 ) {
214- Index idx = createIndex (cctx , factory , definition );
219+ IndexFactory dynamicFactory = (gcctx , indexDefinition ) -> {
220+ Index idx = factory .createIndex (gcctx , indexDefinition );
221+
222+ assert ddlLock .isWriteLockedByCurrentThread ();
223+
224+ if (fillingIdxs == null )
225+ fillingIdxs = new HashSet <>();
226+
227+ fillingIdxs .add (indexDefinition .idxName ());
228+
229+ return idx ;
230+ };
231+
232+ try {
233+ Index idx = createIndex (cctx , dynamicFactory , definition );
215234
216- // Populate index with cache rows.
217- cacheVisitor .visit (row -> {
218- if (idx .canHandle (row ))
219- idx .onUpdate (null , row , false );
220- });
235+ // Populate index with cache rows.
236+ cacheVisitor .visit (row -> {
237+ if (idx .canHandle (row ))
238+ idx .onUpdate (null , row , false );
239+ });
221240
222- return idx ;
241+ return idx ;
242+ }
243+ finally {
244+ ddlLock .writeLock ().lock ();
245+
246+ try {
247+ if (fillingIdxs != null ) {
248+ fillingIdxs .remove (definition .idxName ());
249+
250+ if (fillingIdxs .isEmpty ())
251+ fillingIdxs = null ;
252+ }
253+ }
254+ finally {
255+ ddlLock .writeLock ().unlock ();
256+ }
257+ }
223258 }
224259
225260 /**
@@ -272,8 +307,18 @@ public void removeIndex(IndexName idxName, boolean softDelete) {
272307
273308 Index idx = idxs .remove (idxName .fullName ());
274309
275- if (idx != null )
310+ if (idx != null ) {
276311 idx .destroy (softDelete );
312+
313+ if (fillingIdxs != null ) {
314+ fillingIdxs .remove (idxName );
315+
316+ if (fillingIdxs .isEmpty ())
317+ fillingIdxs = null ;
318+ }
319+
320+ }
321+
277322 }
278323 finally {
279324 ddlLock .writeLock ().unlock ();
@@ -371,16 +416,33 @@ public IndexesRebuildTask idxRebuild() {
371416 * @return Collection of indexes for specified cache.
372417 */
373418 public Collection <Index > indexes (String cacheName ) {
419+ return indexes (cacheName , false );
420+ }
421+
422+ /**
423+ * Returns collection of indexes for specified cache.
424+ *
425+ * @param cacheName Cache name.
426+ * @param skipFilling If {@code true}, indexes that are currently being initially populated are excluded
427+ * from the result; if {@code false}, all known indexes for the cache are returned.
428+ * @return Collection of indexes for specified cache.
429+ */
430+
431+ public Collection <Index > indexes (String cacheName , boolean skipFilling ) {
374432 ddlLock .readLock ().lock ();
375433
376434 try {
377- Map <String , Index > idxs = cacheToIdx .get (cacheName );
435+ Map <String , Index > idxMap = cacheToIdx .get (cacheName );
378436
379- if (idxs == null )
437+ if (idxMap == null )
380438 return Collections .emptyList ();
381439
382- return idxs .values ();
440+ List < Index > idxs = new ArrayList <>( idxMap .values () );
383441
442+ if (skipFilling && fillingIdxs != null )
443+ idxs .removeIf (idx -> fillingIdxs .contains (idx .indexDefinition ().idxName ()));
444+
445+ return idxs ;
384446 }
385447 finally {
386448 ddlLock .readLock ().unlock ();
@@ -394,9 +456,26 @@ public Collection<Index> indexes(String cacheName) {
394456 * @return Index for specified index name or {@code null} if not found.
395457 */
396458 public @ Nullable Index index (IndexName idxName ) {
459+ return index (idxName , false );
460+ }
461+
462+ /**
463+ * Returns index for specified name.
464+ *
465+ * @param idxName Index name.
466+ * @param skipFilling If {@code true}, returns {@code null} when the index is currently being initially
467+ * populated and therefore should be skipped; if {@code false}, returns the index if present.
468+ * @return Index for specified index name or {@code null} if not found (or skipped due to population when
469+ * {@code skipFilling} is {@code true}).
470+ */
471+
472+ public @ Nullable Index index (IndexName idxName , boolean skipFilling ) {
397473 ddlLock .readLock ().lock ();
398474
399475 try {
476+ if (skipFilling && fillingIdxs != null && fillingIdxs .contains (idxName ))
477+ return null ;
478+
400479 Map <String , Index > idxs = cacheToIdx .get (idxName .cacheName ());
401480
402481 if (idxs == null )
0 commit comments