Implemented.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/898e82a2 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/898e82a2 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/898e82a2 Branch: refs/heads/ignite-10291 Commit: 898e82a27dd8a0ec7773eaa5b1e641c12c6c64cd Parents: b35634b Author: devozerov <voze...@gridgain.com> Authored: Wed Nov 28 15:27:55 2018 +0300 Committer: devozerov <voze...@gridgain.com> Committed: Wed Nov 28 15:27:55 2018 +0300 ---------------------------------------------------------------------- .../cache/IgniteCacheOffheapManager.java | 11 ++ .../cache/IgniteCacheOffheapManagerImpl.java | 7 ++ .../GridCacheDatabaseSharedManager.java | 14 ++- .../persistence/GridCacheOffheapManager.java | 5 + .../cache/persistence/IndexStorage.java | 11 ++ .../cache/persistence/IndexStorageImpl.java | 62 ++++------- .../processors/query/GridQueryIndexing.java | 16 +-- .../processors/query/GridQueryProcessor.java | 82 +++----------- ...IgniteClientCacheInitializationFailTest.java | 10 +- .../processors/query/h2/IgniteH2Indexing.java | 107 ++++++++++++++----- .../processors/query/h2/IndexBuildClosure.java | 54 ++++++++++ .../query/h2/IndexRebuildClosure.java | 36 +++++++ .../query/h2/IndexRebuildFullClosure.java | 55 ++++++++++ .../query/h2/IndexRebuildPartialClosure.java | 82 ++++++++++++++ .../query/h2/RebuildIndexFromHashClosure.java | 47 -------- .../query/h2/database/H2TreeIndex.java | 58 +++++++--- .../processors/query/h2/opt/GridH2Table.java | 27 ++++- .../query/h2/GridIndexRebuildSelfTest.java | 7 +- 18 files changed, 465 insertions(+), 226 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java index ed3697a..409d387 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java @@ -602,6 +602,17 @@ public interface IgniteCacheOffheapManager { public void dropRootPageForIndex(int cacheId, String idxName, int segment) throws IgniteCheckedException; /** + * Check if index root page exists. + * + * @param cacheId Cache ID. + * @param idxName Index name. + * @param segment Segment. + * @return {@code True} if exists. + * @throws IgniteCheckedException If failed. + */ + public boolean rootPageForIndexExists(int cacheId, String idxName, int segment) throws IgniteCheckedException; + + /** * @param idxName Index name. * @return Reuse list for index tree. * @throws IgniteCheckedException If failed. http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java index ca14f68..eeae562 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java @@ -1154,6 +1154,13 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager } /** {@inheritDoc} */ + @Override public boolean rootPageForIndexExists(int cacheId, String idxName, int segment) { + assert false : "Should not be called in in-memory mode."; + + return false; + } + + /** {@inheritDoc} */ @Override public ReuseList reuseListForIndex(String idxName) { return grp.reuseList(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java index c9bf673..eb9e4df 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java @@ -137,6 +137,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageParti import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer; import org.apache.ignite.internal.processors.cache.persistence.wal.crc.IgniteDataIntegrityViolationException; import org.apache.ignite.internal.processors.port.GridPortRecord; +import org.apache.ignite.internal.processors.query.GridQueryProcessor; import org.apache.ignite.internal.util.GridMultiCollectionWrapper; import org.apache.ignite.internal.util.IgniteUtils; import org.apache.ignite.internal.util.future.CountDownFuture; @@ -1330,20 +1331,17 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan /** {@inheritDoc} */ @Override public void rebuildIndexesIfNeeded(GridDhtPartitionsExchangeFuture fut) { - if (cctx.kernalContext().query().moduleEnabled()) { + GridQueryProcessor qryProc = cctx.kernalContext().query(); + + if (qryProc.moduleEnabled()) { for (final GridCacheContext cacheCtx : (Collection<GridCacheContext>)cctx.cacheContexts()) { if (cacheCtx.startTopologyVersion().equals(fut.initialVersion())) { final int cacheId = cacheCtx.cacheId(); final GridFutureAdapter<Void> usrFut = idxRebuildFuts.get(cacheId); - boolean persistentNode = cacheCtx.affinityNode() && cacheCtx.group().persistenceEnabled(); - - // TODO: Index rebuild check. - - if (!cctx.pageStore().hasIndexStore(cacheCtx.groupId()) && persistentNode) { - IgniteInternalFuture<?> rebuildFut = cctx.kernalContext().query() - .rebuildIndexesFromHash(Collections.singleton(cacheCtx.cacheId())); + IgniteInternalFuture<?> rebuildFut = qryProc.rebuildIndexesFromHash(cacheCtx); + if (rebuildFut != null) { assert usrFut != null : "Missing user future for cache: " + cacheCtx.name(); rebuildFut.listen(new CI1<IgniteInternalFuture>() { http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java index e1bd8dd..73bf50a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java @@ -846,6 +846,11 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple } /** {@inheritDoc} */ + @Override public boolean rootPageForIndexExists(int cacheId, String idxName, int segment) { + return indexStorage.cacheIndexExists(cacheId, idxName, segment); + } + + /** {@inheritDoc} */ @Override public ReuseList reuseListForIndex(String idxName) { return reuseList; } http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorage.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorage.java index 295ff00..1e656ef 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorage.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorage.java @@ -65,6 +65,17 @@ public interface IndexStorage { public RootPage dropIndex(String idxName) throws IgniteCheckedException; /** + * Check if cache index exists. + * + * @param cacheId Cache ID. + * @param idxName Index name. + * @param segment Segment. + * @return {@code True} if exists. + * @throws IgniteCheckedException If failed. + */ + public boolean cacheIndexExists(Integer cacheId, String idxName, int segment) throws IgniteCheckedException; + + /** * Destroy this meta store. * * @throws IgniteCheckedException If failed. http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java index bb244ab..4235cae 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java @@ -33,7 +33,6 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersion import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList; import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler; import org.apache.ignite.internal.processors.failure.FailureProcessor; -import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.U; import org.jetbrains.annotations.Nullable; @@ -107,9 +106,9 @@ public class IndexStorageImpl implements IndexStorage { /** {@inheritDoc} */ @Override public RootPage allocateCacheIndex(Integer cacheId, String idxName, int segment) throws IgniteCheckedException { - String mangledIdxName = mangleCacheIndexName(cacheId, idxName, segment); + String maskedIdxName = maskCacheIndexName(cacheId, idxName, segment); - return allocateIndex(mangledIdxName); + return allocateIndex(maskedIdxName); } /** {@inheritDoc} */ @@ -148,9 +147,9 @@ public class IndexStorageImpl implements IndexStorage { /** {@inheritDoc} */ @Override public RootPage dropCacheIndex(Integer cacheId, String idxName, int segment) throws IgniteCheckedException { - String mangledIdxName = mangleCacheIndexName(cacheId, idxName, segment); + String maskedIdxName = maskCacheIndexName(cacheId, idxName, segment); - return dropIndex(mangledIdxName); + return dropIndex(maskedIdxName); } /** {@inheritDoc} */ @@ -168,17 +167,29 @@ public class IndexStorageImpl implements IndexStorage { } /** {@inheritDoc} */ + @Override public boolean cacheIndexExists(Integer cacheId, String idxName, int segment) + throws IgniteCheckedException { + String maskedIdxName = maskCacheIndexName(cacheId, idxName, segment); + + byte[] idxNameBytes = maskedIdxName.getBytes(StandardCharsets.UTF_8); + + IndexItem row = metaTree.findOne(new IndexItem(idxNameBytes, 0)); + + return row != null; + } + + /** {@inheritDoc} */ @Override public void destroy() throws IgniteCheckedException { metaTree.destroy(); } /** - * Mange cache index name. + * Mask cache index name. * * @param idxName Index name. - * @return Mangled name. + * @return Masked name. */ - private String mangleCacheIndexName(Integer cacheId, String idxName, int segment) { + private String maskCacheIndexName(Integer cacheId, String idxName, int segment) { assert !grpShared || grpId == cacheId; if (grpShared) @@ -188,41 +199,6 @@ public class IndexStorageImpl implements IndexStorage { } /** - * Unmangle cache index name if possible. - * - * @param mangledIdxName Mangled index name. - * @param expCacheId Expected cache ID. - * @return Unmangled index name, {@code null} if doesn't match expected cache ID. - * @throws IgniteCheckedException If failed. - */ - @Nullable private String unmangleCacheIndexNameIfPossible(String mangledIdxName, Integer expCacheId) - throws IgniteCheckedException { - if (grpShared) - return mangledIdxName; - else { - int pos = mangledIdxName.indexOf('_'); - - if (pos != -1) { - String cacheIdStr = mangledIdxName.substring(0, pos - 1); - String idxName = mangledIdxName.substring(pos); - - try { - Integer cacheId = Integer.parseInt(cacheIdStr); - - if (F.eq(expCacheId, cacheId)) - return idxName; - } - catch (NumberFormatException e) { - throw new IgniteCheckedException("Failed to parse cache ID of mangled index name: " + - mangledIdxName); - } - } - - return null; - } - } - - /** * */ private static class MetaTree extends BPlusTree<IndexItem, IndexItem> { http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java index dab2516..d1e5d14 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java @@ -27,6 +27,7 @@ import org.apache.ignite.cache.query.FieldsQueryCursor; import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.cache.query.SqlQuery; import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.mvcc.MvccQueryTracker; @@ -273,19 +274,12 @@ public interface GridQueryIndexing { throws IgniteCheckedException; /** - * Rebuilds all indexes of given type from hash index. + * Rebuild indexes for the given cache if necessary. * - * @param cacheName Cache name. - * @throws IgniteCheckedException If failed. - */ - public void rebuildIndexesFromHash(String cacheName) throws IgniteCheckedException; - - /** - * Marks all indexes of given type for rebuild from hash index, making them unusable until rebuild finishes. - * - * @param cacheName Cache name. + * @param cctx Cache context. + * @return Future completed when index rebuild finished. */ - public void markForRebuildFromHash(String cacheName); + public IgniteInternalFuture<?> rebuildIndexesFromHash(GridCacheContext cctx); /** * Returns backup filter. http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java index 95ff3d5..16b011f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java @@ -93,7 +93,6 @@ import org.apache.ignite.internal.processors.query.schema.operation.SchemaIndexD import org.apache.ignite.internal.processors.timeout.GridTimeoutProcessor; import org.apache.ignite.internal.util.GridBoundedConcurrentLinkedHashSet; import org.apache.ignite.internal.util.GridSpinBusyLock; -import org.apache.ignite.internal.util.future.GridCompoundFuture; import org.apache.ignite.internal.util.future.GridFinishedFuture; import org.apache.ignite.internal.util.lang.GridCloseableIterator; import org.apache.ignite.internal.util.lang.GridClosureException; @@ -106,8 +105,6 @@ import org.apache.ignite.internal.util.typedef.internal.CU; import org.apache.ignite.internal.util.typedef.internal.LT; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.internal.util.worker.GridWorker; -import org.apache.ignite.internal.util.worker.GridWorkerFuture; import org.apache.ignite.lang.IgniteBiTuple; import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.lang.IgniteInClosure; @@ -1749,30 +1746,28 @@ public class GridQueryProcessor extends GridProcessorAdapter { /** * Rebuilds indexes for provided caches from corresponding hash indexes. * - * @param cacheIds Cache IDs. + * @param cctx Cache context. * @return Future that will be completed when rebuilding is finished. */ - public IgniteInternalFuture<?> rebuildIndexesFromHash(Set<Integer> cacheIds) { - if (!busyLock.enterBusy()) - return new GridFinishedFuture<>(new NodeStoppingException("Failed to rebuild indexes from hash (grid is stopping).")); - - // Because of alt type ids, there can be few entries in 'types' for a single cache. - // In order to avoid processing a cache more than once, let's track processed names. - Set<String> processedCacheNames = new HashSet<>(); - - try { - GridCompoundFuture<Object, ?> fut = new GridCompoundFuture<Object, Object>(); + public IgniteInternalFuture<?> rebuildIndexesFromHash(GridCacheContext cctx) { + // Indexing module is disabled, nothing to rebuild. + if (idx == null) + return null; - for (Map.Entry<QueryTypeIdKey, QueryTypeDescriptorImpl> e : types.entrySet()) { - String cacheName = e.getKey().cacheName(); + // No data on non-affinity nodes. + if (!cctx.affinityNode()) + return null; - if (cacheIds.contains(CU.cacheId(cacheName)) && processedCacheNames.add(cacheName)) - fut.add(rebuildIndexesFromHash(cacheName, e.getValue())); - } + // No indexes to rebuild when there are no QueryEntities. + if (!cctx.isQueryEnabled()) + return null; - fut.markInitialized(); + if (!busyLock.enterBusy()) + return new GridFinishedFuture<>(new NodeStoppingException("Failed to rebuild indexes from hash " + + "(grid is stopping).")); - return fut; + try { + return idx.rebuildIndexesFromHash(cctx); } finally { busyLock.leaveBusy(); @@ -1781,51 +1776,6 @@ public class GridQueryProcessor extends GridProcessorAdapter { /** * @param cacheName Cache name. - * @param desc Type descriptor. - * @return Future that will be completed when rebuilding of all indexes is finished. - */ - private IgniteInternalFuture<Object> rebuildIndexesFromHash(@Nullable final String cacheName, - @Nullable final QueryTypeDescriptorImpl desc) { - if (idx == null) - return new GridFinishedFuture<>(new IgniteCheckedException("Indexing is disabled.")); - - if (desc == null) - return new GridFinishedFuture<>(); - - final GridWorkerFuture<Object> fut = new GridWorkerFuture<>(); - - idx.markForRebuildFromHash(cacheName); - - GridWorker w = new GridWorker(ctx.igniteInstanceName(), "index-rebuild-worker", log) { - @Override protected void body() { - try { - idx.rebuildIndexesFromHash(cacheName); - - fut.onDone(); - } - catch (Exception e) { - fut.onDone(e); - } - catch (Throwable e) { - U.error(log, "Failed to rebuild indexes for type [cache=" + cacheName + - ", name=" + desc.name() + ']', e); - - fut.onDone(e); - - throw e; - } - } - }; - - fut.setWorker(w); - - ctx.getExecutorService().execute(w); - - return fut; - } - - /** - * @param cacheName Cache name. * @return Cache object context. */ private CacheObjectContext cacheObjectContext(String cacheName) { http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java index 5432257..d889cb5 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java @@ -39,6 +39,7 @@ import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.IgniteKernal; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.mvcc.MvccQueryTracker; @@ -336,13 +337,8 @@ public class IgniteClientCacheInitializationFailTest extends GridCommonAbstractT } /** {@inheritDoc} */ - @Override public void rebuildIndexesFromHash(String cacheName) throws IgniteCheckedException { - // No-op - } - - /** {@inheritDoc} */ - @Override public void markForRebuildFromHash(String cacheName) { - // No-op + @Override public IgniteInternalFuture<?> rebuildIndexesFromHash(GridCacheContext cctx) { + return null; } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java index 937363a..6582516 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java @@ -58,6 +58,7 @@ import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.GridTopic; import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.CacheObjectValueContext; import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor; @@ -74,7 +75,6 @@ import org.apache.ignite.internal.processors.cache.mvcc.MvccUtils; import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO; import org.apache.ignite.internal.processors.query.h2.affinity.PartitionInfo; -import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager; import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable; import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery; import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; @@ -113,7 +113,6 @@ import org.apache.ignite.internal.processors.query.h2.dml.DmlUtils; import org.apache.ignite.internal.processors.query.h2.dml.UpdatePlan; import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase; import org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext; -import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row; import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor; import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table; import org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias; @@ -164,6 +163,8 @@ import org.apache.ignite.internal.util.typedef.internal.CU; import org.apache.ignite.internal.util.typedef.internal.LT; import org.apache.ignite.internal.util.typedef.internal.SB; import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.internal.util.worker.GridWorker; +import org.apache.ignite.internal.util.worker.GridWorkerFuture; import org.apache.ignite.lang.IgniteBiClosure; import org.apache.ignite.lang.IgniteBiTuple; import org.apache.ignite.lang.IgniteFuture; @@ -642,15 +643,7 @@ public class IgniteH2Indexing implements GridQueryIndexing { // Populate index with existing cache data. final GridH2RowDescriptor rowDesc = h2Tbl.rowDescriptor(); - SchemaIndexCacheVisitorClosure clo = new SchemaIndexCacheVisitorClosure() { - @Override public void apply(CacheDataRow row) throws IgniteCheckedException { - GridH2Row h2Row = rowDesc.createRow(row); - - h2Idx.putx(h2Row); - } - }; - - cacheVisitor.visit(clo); + cacheVisitor.visit(new IndexBuildClosure(rowDesc, h2Idx)); // At this point index is in consistent state, promote it through H2 SQL statement, so that cached // prepared statements are re-built. @@ -2694,33 +2687,93 @@ public class IgniteH2Indexing implements GridQueryIndexing { return rowCache.forGroup(grpId); } + /** {@inheritDoc} */ + @Override public IgniteInternalFuture<?> rebuildIndexesFromHash(GridCacheContext cctx) { + // No data in fresh in-memory cache. + if (!cctx.group().persistenceEnabled()) + return null; + + IgnitePageStoreManager pageStore = cctx.shared().pageStore(); + + assert pageStore != null; + + IndexRebuildClosure clo; + + if (!pageStore.hasIndexStore(cctx.groupId())) { + // If there are no index store, rebuild all indexes. + clo = new IndexRebuildFullClosure(cctx.queries(), cctx.mvccEnabled()); + } + else { + // Otherwise iterate over tables looking for missing indexes. + clo = new IndexRebuildPartialClosure(); + + for (H2TableDescriptor tblDesc : tables(cctx.name())) { + assert tblDesc.table() != null; + + tblDesc.table().collectIndexesForPartialRebuild((IndexRebuildPartialClosure)clo); + } + } + + // Closure prepared, do rebuild. + final GridWorkerFuture<?> fut = new GridWorkerFuture<>(); + + markIndexRebuild(cctx.name(), clo, true); + + GridWorker worker = new GridWorker(ctx.igniteInstanceName(), "index-rebuild-worker-" + cctx.name(), log) { + @Override protected void body() { + try { + rebuildIndexesFromHash0(cctx, clo); + + markIndexRebuild(cctx.name(), clo, false); + + fut.onDone(); + } + catch (Exception e) { + fut.onDone(e); + } + catch (Throwable e) { + U.error(log, "Failed to rebuild indexes for cache: " + cctx.name(), e); + + fut.onDone(e); + + throw e; + } + } + }; + + fut.setWorker(worker); + + ctx.getExecutorService().execute(worker); + + return fut; + } + /** - * Rebuild indexes from hash index. + * Do index rebuild. * - * @param cacheName Cache name. + * @param cctx Cache context. + * @param clo Closure. * @throws IgniteCheckedException If failed. */ - @Override public void rebuildIndexesFromHash(String cacheName) throws IgniteCheckedException { - int cacheId = CU.cacheId(cacheName); - - GridCacheContext cctx = ctx.cache().context().cacheContext(cacheId); - - final GridCacheQueryManager qryMgr = cctx.queries(); - + protected void rebuildIndexesFromHash0(GridCacheContext cctx, SchemaIndexCacheVisitorClosure clo) + throws IgniteCheckedException { SchemaIndexCacheVisitor visitor = new SchemaIndexCacheVisitorImpl(cctx); - visitor.visit(new RebuildIndexFromHashClosure(qryMgr, cctx.mvccEnabled())); - - for (H2TableDescriptor tblDesc : tables(cacheName)) - tblDesc.table().markRebuildFromHashInProgress(false); + visitor.visit(clo); } - /** {@inheritDoc} */ - @Override public void markForRebuildFromHash(String cacheName) { + /** + * Mark tables for index rebuild, so that their indexes are not used. + * + * @param cacheName Cache name. + * @param val Value. + */ + private void markIndexRebuild(String cacheName, IndexRebuildClosure clo, boolean val) { for (H2TableDescriptor tblDesc : tables(cacheName)) { assert tblDesc.table() != null; - tblDesc.table().markRebuildFromHashInProgress(true); + // TODO: Mark only some indexes. + tblDesc.table().markRebuildFromHashInProgress(val); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexBuildClosure.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexBuildClosure.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexBuildClosure.java new file mode 100644 index 0000000..95a5adf --- /dev/null +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexBuildClosure.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.h2; + +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor; +import org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitorClosure; + +/** + * Index build closure. + */ +public class IndexBuildClosure implements SchemaIndexCacheVisitorClosure { + /** Row descriptor. */ + private final GridH2RowDescriptor rowDesc; + + /** Index. */ + private final GridH2IndexBase idx; + + /** + * Constructor. + * + * @param rowDesc Row descriptor. + * @param idx Target index. + */ + public IndexBuildClosure(GridH2RowDescriptor rowDesc, GridH2IndexBase idx) { + this.rowDesc = rowDesc; + this.idx = idx; + } + + /** {@inheritDoc} */ + @Override public void apply(CacheDataRow row) throws IgniteCheckedException { + GridH2Row h2Row = rowDesc.createRow(row); + + idx.putx(h2Row); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildClosure.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildClosure.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildClosure.java new file mode 100644 index 0000000..75943dd --- /dev/null +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildClosure.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.h2; + +import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table; +import org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitorClosure; + +/** + * Index rebuild closure. Exposes information about indexes being rebuilt. + */ +public interface IndexRebuildClosure extends SchemaIndexCacheVisitorClosure { + /** + * Check if the given index is being rebuild by this closure. + * + * @param tbl Table. + * @param idx Index. + * @return {@code True} if index is being rebuild by this closure, {@code false} otherwise. + */ + boolean isRebuilt(GridH2Table tbl, GridH2IndexBase idx); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildFullClosure.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildFullClosure.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildFullClosure.java new file mode 100644 index 0000000..e070382 --- /dev/null +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildFullClosure.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.h2; + +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; +import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table; + +/** + * Closure to rebuild all indexes. + */ +public class IndexRebuildFullClosure implements IndexRebuildClosure { + /** */ + private final GridCacheQueryManager qryMgr; + + /** MVCC status flag. */ + private final boolean mvccEnabled; + + /** + * @param qryMgr Query manager. + * @param mvccEnabled MVCC status flag. + */ + public IndexRebuildFullClosure(GridCacheQueryManager qryMgr, boolean mvccEnabled) { + this.qryMgr = qryMgr; + this.mvccEnabled = mvccEnabled; + } + + /** {@inheritDoc} */ + @Override public void apply(CacheDataRow row) throws IgniteCheckedException { + // prevRowAvailable is always true with MVCC on, and always false *on index rebuild* with MVCC off. + qryMgr.store(row, null, mvccEnabled); + } + + /** {@inheritDoc} */ + @Override public boolean isRebuilt(GridH2Table tbl, GridH2IndexBase idx) { + return true; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildPartialClosure.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildPartialClosure.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildPartialClosure.java new file mode 100644 index 0000000..e40b364 --- /dev/null +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildPartialClosure.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.h2; + +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table; + +import java.util.Collection; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Map; + +/** + * Closure to rebuild some cache indexes. + */ +public class IndexRebuildPartialClosure implements IndexRebuildClosure { + /** Indexes. */ + private final Map<GridH2Table, Collection<GridH2IndexBase>> tblIdxs = new IdentityHashMap<>(); + + /** {@inheritDoc} */ + @Override public void apply(CacheDataRow row) throws IgniteCheckedException { + assert hasIndexes(); + + for (Map.Entry<GridH2Table, Collection<GridH2IndexBase>> tblIdxEntry : tblIdxs.entrySet()) { + GridH2Table tbl = tblIdxEntry.getKey(); + + GridH2Row row0 = tbl.rowDescriptor().createRow(row); + + for (GridH2IndexBase idx : tblIdxEntry.getValue()) + idx.putx(row0); + } + } + + /** {@inheritDoc} */ + @Override public boolean isRebuilt(GridH2Table tbl, GridH2IndexBase idx) { + Collection<GridH2IndexBase> idxs = tblIdxs.get(tbl); + + return idxs != null && idxs.contains(idx); + } + + /** + * @param idx Index to be rebuilt. + */ + public void addIndex(GridH2Table tbl, GridH2IndexBase idx) { + Collection<GridH2IndexBase> idxs = tblIdxs.get(tbl); + + if (idxs == null) { + idxs = Collections.newSetFromMap(new IdentityHashMap<>()); + + idxs.add(idx); + + tblIdxs.put(tbl, idxs); + } + + idxs.add(idx); + } + + /** + * @return {@code True} if there is at least one index to rebuild. + */ + public boolean hasIndexes() { + return !tblIdxs.isEmpty(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/RebuildIndexFromHashClosure.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/RebuildIndexFromHashClosure.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/RebuildIndexFromHashClosure.java deleted file mode 100644 index b635eac..0000000 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/RebuildIndexFromHashClosure.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.internal.processors.query.h2; - -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; -import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager; -import org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitorClosure; - -/** */ -class RebuildIndexFromHashClosure implements SchemaIndexCacheVisitorClosure { - /** */ - private final GridCacheQueryManager qryMgr; - - /** MVCC status flag. */ - private final boolean mvccEnabled; - - /** - * @param qryMgr Query manager. - * @param mvccEnabled MVCC status flag. - */ - RebuildIndexFromHashClosure(GridCacheQueryManager qryMgr, boolean mvccEnabled) { - this.qryMgr = qryMgr; - this.mvccEnabled = mvccEnabled; - } - - /** {@inheritDoc} */ - @Override public void apply(CacheDataRow row) throws IgniteCheckedException { - // prevRowAvailable is always true with MVCC on, and always false *on index rebuild* with MVCC off. - qryMgr.store(row, null, mvccEnabled); - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java index b0d9e23..48d4cc4 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java @@ -88,6 +88,9 @@ public class H2TreeIndex extends GridH2IndexBase { /** */ private final String idxName; + /** Tree name. */ + private final String treeName; + /** */ private final IgniteLogger log; @@ -130,14 +133,11 @@ public class H2TreeIndex extends GridH2IndexBase { this.table = tbl; - GridQueryTypeDescriptor typeDesc = tbl.rowDescriptor().type(); int typeId = cctx.binaryMarshaller() ? typeDesc.typeId() : typeDesc.valueClass().hashCode(); - String treeName = (tbl.rowDescriptor() == null ? "" : typeId + "_") + idxName; - - treeName = BPlusTree.treeName(treeName, "H2Tree"); + treeName = BPlusTree.treeName((tbl.rowDescriptor() == null ? "" : typeId + "_") + idxName, "H2Tree"); IndexColumnsInfo unwrappedColsInfo = new IndexColumnsInfo(unwrappedColsList, inlineSize); @@ -156,7 +156,7 @@ public class H2TreeIndex extends GridH2IndexBase { db.checkpointReadLock(); try { - RootPage page = getMetaPage(treeName, i); + RootPage page = getMetaPage(i); segments[i] = new H2Tree( treeName, @@ -215,6 +215,29 @@ public class H2TreeIndex extends GridH2IndexBase { } /** + * Check if index exists in store. + * + * @return {@code True} if exists. + */ + public boolean rebuildRequired() { + assert segments != null; + + for (int i = 0; i < segments.length; i++) { + try { + + if (!metaPageExists(i)) + return true; + } + catch (Exception e) { + throw new IgniteException("Failed to check index tree root page existence [cacheName=" + cctx.name() + + ", tblName=" + tblName + ", idxName=" + idxName + ", segment=" + i + ']'); + } + } + + return false; + } + + /** * @param cols Columns array. * @return List of {@link InlineIndexHelper} objects. */ @@ -431,7 +454,7 @@ public class H2TreeIndex extends GridH2IndexBase { tree.destroy(); - dropMetaPage(tree.getName(), i); + dropMetaPage(i); } } } @@ -526,22 +549,31 @@ public class H2TreeIndex extends GridH2IndexBase { } /** - * @param name Name. * @param segIdx Segment index. * @return RootPage for meta page. * @throws IgniteCheckedException If failed. */ - private RootPage getMetaPage(String name, int segIdx) throws IgniteCheckedException { - return cctx.offheap().rootPageForIndex(cctx.cacheId(), name, segIdx); + private RootPage getMetaPage(int segIdx) throws IgniteCheckedException { + return cctx.offheap().rootPageForIndex(cctx.cacheId(), treeName, segIdx); + } + + /** + * @param segIdx Segment index. + * @throws IgniteCheckedException If failed. + */ + private void dropMetaPage(int segIdx) throws IgniteCheckedException { + cctx.offheap().dropRootPageForIndex(cctx.cacheId(), treeName, segIdx); } /** - * @param name Name. + * Check if index meta page exists. + * * @param segIdx Segment index. + * @return {@code True} if exists. * @throws IgniteCheckedException If failed. */ - private void dropMetaPage(String name, int segIdx) throws IgniteCheckedException { - cctx.offheap().dropRootPageForIndex(cctx.cacheId(), name, segIdx); + private boolean metaPageExists(int segIdx) throws IgniteCheckedException { + return cctx.offheap().rootPageForIndexExists(cctx.cacheId(), treeName, segIdx); } /** {@inheritDoc} */ @@ -575,7 +607,7 @@ public class H2TreeIndex extends GridH2IndexBase { * @param cfgInlineSize Inline size from cache config. */ public IndexColumnsInfo(List<IndexColumn> colsList, int cfgInlineSize) { - this.cols = colsList.toArray(new IndexColumn[colsList.size()]); + this.cols = colsList.toArray(new IndexColumn[0]); this.inlineIdx = getAvailableInlineColumns(cols); http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java index b2da670..eafb813 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java @@ -35,6 +35,7 @@ import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; import org.apache.ignite.internal.processors.cache.query.QueryTable; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.QueryField; +import org.apache.ignite.internal.processors.query.h2.IndexRebuildPartialClosure; import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory; import org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex; import org.apache.ignite.internal.processors.query.h2.twostep.GridMapQueryExecutor; @@ -174,11 +175,14 @@ public class GridH2Table extends TableBase { assert idxs != null; List<Index> clones = new ArrayList<>(idxs.size()); + for (Index index : idxs) { Index clone = createDuplicateIndexIfNeeded(index); + if (clone != null) clones.add(clone); } + idxs.addAll(clones); boolean hasHashIndex = idxs.size() >= 2 && index(0).getIndexType().isHash(); @@ -550,6 +554,24 @@ public class GridH2Table extends TableBase { } /** + * Collect indexes for rebuild. + * + * @param clo Closure. + */ + public void collectIndexesForPartialRebuild(IndexRebuildPartialClosure clo) { + for (int i = sysIdxsCnt; i < idxs.size(); i++) { + Index idx = idxs.get(i); + + if (idx instanceof H2TreeIndex) { + H2TreeIndex idx0 = (H2TreeIndex)idx; + + if (idx0.rebuildRequired()) + clo.addIndex(this, idx0); + } + } + } + + /** * */ public void markRebuildFromHashInProgress(boolean value) { @@ -948,9 +970,10 @@ public class GridH2Table extends TableBase { } /** + * Drop columns. * - * @param cols - * @param ifExists + * @param cols Columns. + * @param ifExists If EXISTS flag. */ public void dropColumns(List<String> cols, boolean ifExists) { assert !ifExists || cols.size() == 1; http://git-wip-us.apache.org/repos/asf/ignite/blob/898e82a2/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexRebuildSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexRebuildSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexRebuildSelfTest.java index c5f1441..fe841ae 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexRebuildSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexRebuildSelfTest.java @@ -24,12 +24,14 @@ import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManager; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.cache.index.DynamicIndexAbstractSelfTest; import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager; import org.apache.ignite.internal.processors.query.GridQueryProcessor; +import org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitorClosure; import org.apache.ignite.internal.util.lang.GridCursor; import org.apache.ignite.internal.util.typedef.internal.U; @@ -228,13 +230,14 @@ public class GridIndexRebuildSelfTest extends DynamicIndexAbstractSelfTest { private boolean firstRbld = true; /** {@inheritDoc} */ - @Override public void rebuildIndexesFromHash(String cacheName) throws IgniteCheckedException { + @Override protected void rebuildIndexesFromHash0(GridCacheContext cctx, SchemaIndexCacheVisitorClosure clo) + throws IgniteCheckedException { if (!firstRbld) U.await(INSTANCE.rebuildLatch); else firstRbld = false; - super.rebuildIndexesFromHash(cacheName); + super.rebuildIndexesFromHash0(cctx, clo); } } }