IGNITE-10291: SQL: fixed index re-build routine. Now indexes which appeared during node shutdown are rebuilt as well. This closes #5525.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/9b0ce92d Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/9b0ce92d Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/9b0ce92d Branch: refs/heads/ignite-10044 Commit: 9b0ce92d9f60004ec07cff137d7b0582c644a500 Parents: d19123d Author: devozerov <voze...@gridgain.com> Authored: Mon Dec 3 18:08:53 2018 +0300 Committer: devozerov <voze...@gridgain.com> Committed: Mon Dec 3 18:08:53 2018 +0300 ---------------------------------------------------------------------- .../cache/IgniteCacheOffheapManager.java | 5 +- .../cache/IgniteCacheOffheapManagerImpl.java | 4 +- .../GridCacheDatabaseSharedManager.java | 14 +- .../persistence/GridCacheOffheapManager.java | 15 +- .../cache/persistence/IndexStorage.java | 26 ++- .../cache/persistence/IndexStorageImpl.java | 37 +++- .../UpgradePendingTreeToPerPartitionTask.java | 4 +- .../processors/query/GridQueryIndexing.java | 16 +- .../processors/query/GridQueryProcessor.java | 92 +++------- ...IgniteClientCacheInitializationFailTest.java | 10 +- .../database/IndexStorageSelfTest.java | 21 ++- .../processors/query/h2/IgniteH2Indexing.java | 113 +++++++++--- .../processors/query/h2/IndexBuildClosure.java | 54 ++++++ .../query/h2/IndexRebuildFullClosure.java | 49 +++++ .../query/h2/IndexRebuildPartialClosure.java | 76 ++++++++ .../query/h2/RebuildIndexFromHashClosure.java | 47 ----- .../processors/query/h2/database/H2Tree.java | 14 ++ .../query/h2/database/H2TreeIndex.java | 48 +++-- .../processors/query/h2/opt/GridH2Table.java | 56 +++++- .../cache/IgniteDynamicSqlRestoreTest.java | 180 +++++++++++++++++-- .../query/h2/GridIndexRebuildSelfTest.java | 9 +- 21 files changed, 667 insertions(+), 223 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 cdc44a5..ed3697a 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 @@ -588,17 +588,18 @@ public interface IgniteCacheOffheapManager { /** * @param cacheId Cache ID. * @param idxName Index name. + * @param segment Segment. * @return Root page for index tree. * @throws IgniteCheckedException If failed. */ - public RootPage rootPageForIndex(int cacheId, String idxName) throws IgniteCheckedException; + public RootPage rootPageForIndex(int cacheId, String idxName, int segment) throws IgniteCheckedException; /** * @param cacheId Cache ID. * @param idxName Index name. * @throws IgniteCheckedException If failed. */ - public void dropRootPageForIndex(int cacheId, String idxName) throws IgniteCheckedException; + public void dropRootPageForIndex(int cacheId, String idxName, int segment) throws IgniteCheckedException; /** * @param idxName Index name. http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 e15009e..ca14f68 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 @@ -1142,14 +1142,14 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager } /** {@inheritDoc} */ - @Override public RootPage rootPageForIndex(int cacheId, String idxName) throws IgniteCheckedException { + @Override public RootPage rootPageForIndex(int cacheId, String idxName, int segment) throws IgniteCheckedException { long pageId = allocateForTree(); return new RootPage(new FullPageId(pageId, grp.groupId()), true); } /** {@inheritDoc} */ - @Override public void dropRootPageForIndex(int cacheId, String idxName) throws IgniteCheckedException { + @Override public void dropRootPageForIndex(int cacheId, String idxName, int segment) throws IgniteCheckedException { // No-op. } http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 d610a51..9a03337 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; @@ -1342,16 +1343,19 @@ 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); - if (!cctx.pageStore().hasIndexStore(cacheCtx.groupId()) && cacheCtx.affinityNode() - && cacheCtx.group().persistenceEnabled()) { - IgniteInternalFuture<?> rebuildFut = cctx.kernalContext().query() - .rebuildIndexesFromHash(Collections.singleton(cacheCtx.cacheId())); + IgniteInternalFuture<?> rebuildFut = qryProc.rebuildIndexesFromHash(cacheCtx); + + if (rebuildFut != null) { + log().info("Started indexes rebuilding for cache [name=" + cacheCtx.name() + + ", grpName=" + cacheCtx.group().name() + ']'); assert usrFut != null : "Missing user future for cache: " + cacheCtx.name(); http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 44ae6f1..e1bd8dd 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 @@ -142,6 +142,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple ctx.wal(), globalRemoveId(), grp.groupId(), + grp.sharedGroup(), PageIdAllocator.INDEX_PARTITION, PageIdAllocator.FLAG_IDX, reuseList, @@ -835,19 +836,13 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple } /** {@inheritDoc} */ - @Override public RootPage rootPageForIndex(int cacheId, String idxName) throws IgniteCheckedException { - if (grp.sharedGroup()) - idxName = Integer.toString(cacheId) + "_" + idxName; - - return indexStorage.getOrAllocateForTree(idxName); + @Override public RootPage rootPageForIndex(int cacheId, String idxName, int segment) throws IgniteCheckedException { + return indexStorage.allocateCacheIndex(cacheId, idxName, segment); } /** {@inheritDoc} */ - @Override public void dropRootPageForIndex(int cacheId, String idxName) throws IgniteCheckedException { - if (grp.sharedGroup()) - idxName = Integer.toString(cacheId) + "_" + idxName; - - indexStorage.dropRootPage(idxName); + @Override public void dropRootPageForIndex(int cacheId, String idxName, int segment) throws IgniteCheckedException { + indexStorage.dropCacheIndex(cacheId, idxName, segment); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 5141b04..295ff00 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 @@ -24,6 +24,17 @@ import org.apache.ignite.IgniteCheckedException; */ public interface IndexStorage { /** + * Allocate page for cache index. Index name will be masked if needed. + * + * @param cacheId Cache ID. + * @param idxName Index name. + * @param segment Segment. + * @return Root page. + * @throws IgniteCheckedException If failed. + */ + public RootPage allocateCacheIndex(Integer cacheId, String idxName, int segment) throws IgniteCheckedException; + + /** * Get or allocate initial page for an index. * * @param idxName Index name. @@ -31,7 +42,18 @@ public interface IndexStorage { * was newly allocated, and rootId that is counter which increments each time new page allocated. * @throws IgniteCheckedException If failed. */ - public RootPage getOrAllocateForTree(String idxName) throws IgniteCheckedException; + public RootPage allocateIndex(String idxName) throws IgniteCheckedException; + + /** + * Deallocate index page and remove from tree. + * + * @param cacheId Cache ID. + * @param idxName Index name. + * @param segment Segment. + * @return Root ID or -1 if no page was removed. + * @throws IgniteCheckedException If failed. + */ + public RootPage dropCacheIndex(Integer cacheId, String idxName, int segment) throws IgniteCheckedException; /** * Deallocate index page and remove from tree. @@ -40,7 +62,7 @@ public interface IndexStorage { * @return Root ID or -1 if no page was removed. * @throws IgniteCheckedException If failed. */ - public RootPage dropRootPage(String idxName) throws IgniteCheckedException; + public RootPage dropIndex(String idxName) throws IgniteCheckedException; /** * Destroy this meta store. http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 6248765..b29553c 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 @@ -61,6 +61,9 @@ public class IndexStorageImpl implements IndexStorage { /** Cache group ID. */ private final int grpId; + /** Whether group is shared. */ + private final boolean grpShared; + /** */ private final int allocPartId; @@ -76,6 +79,7 @@ public class IndexStorageImpl implements IndexStorage { final IgniteWriteAheadLogManager wal, final AtomicLong globalRmvId, final int grpId, + boolean grpShared, final int allocPartId, final byte allocSpace, final ReuseList reuseList, @@ -86,6 +90,7 @@ public class IndexStorageImpl implements IndexStorage { try { this.pageMem = pageMem; this.grpId = grpId; + this.grpShared = grpShared; this.allocPartId = allocPartId; this.allocSpace = allocSpace; this.reuseList = reuseList; @@ -99,7 +104,15 @@ public class IndexStorageImpl implements IndexStorage { } /** {@inheritDoc} */ - @Override public RootPage getOrAllocateForTree(final String idxName) throws IgniteCheckedException { + @Override public RootPage allocateCacheIndex(Integer cacheId, String idxName, int segment) + throws IgniteCheckedException { + String maskedIdxName = maskCacheIndexName(cacheId, idxName, segment); + + return allocateIndex(maskedIdxName); + } + + /** {@inheritDoc} */ + @Override public RootPage allocateIndex(String idxName) throws IgniteCheckedException { final MetaTree tree = metaTree; synchronized (this) { @@ -132,8 +145,15 @@ public class IndexStorageImpl implements IndexStorage { } /** {@inheritDoc} */ - @Override public RootPage dropRootPage(final String idxName) + @Override public RootPage dropCacheIndex(Integer cacheId, String idxName, int segment) throws IgniteCheckedException { + String maskedIdxName = maskCacheIndexName(cacheId, idxName, segment); + + return dropIndex(maskedIdxName); + } + + /** {@inheritDoc} */ + @Override public RootPage dropIndex(final String idxName) throws IgniteCheckedException { byte[] idxNameBytes = idxName.getBytes(StandardCharsets.UTF_8); final IndexItem row = metaTree.remove(new IndexItem(idxNameBytes, 0)); @@ -152,6 +172,19 @@ public class IndexStorageImpl implements IndexStorage { } /** + * Mask cache index name. + * + * @param idxName Index name. + * @return Masked name. + */ + private String maskCacheIndexName(Integer cacheId, String idxName, int segment) { + if (grpShared) + idxName = Integer.toString(cacheId) + "_" + idxName; + + return idxName + "%" + segment; + } + + /** * */ private static class MetaTree extends BPlusTree<IndexItem, IndexItem> { http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java index 6fa039d..1cba69a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java @@ -131,14 +131,14 @@ public class UpgradePendingTreeToPerPartitionTask implements IgniteCallable<Bool IndexStorage indexStorage = ((GridCacheOffheapManager)grp.offheap()).getIndexStorage(); //TODO: IGNITE-5874: replace with some check-method to avoid unnecessary page allocation. - RootPage pendingRootPage = indexStorage.getOrAllocateForTree(PENDING_ENTRIES_TREE_NAME); + RootPage pendingRootPage = indexStorage.allocateIndex(PENDING_ENTRIES_TREE_NAME); if (pendingRootPage.isAllocated()) { log.info("No pending tree found for cache group: [grpId=" + grp.groupId() + ", grpName=" + grp.name() + ']'); // Nothing to do here as just allocated tree is obviously empty. - indexStorage.dropRootPage(PENDING_ENTRIES_TREE_NAME); + indexStorage.dropIndex(PENDING_ENTRIES_TREE_NAME); return; } http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 c8c9502..2abafab 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.GridCacheContextInfo; @@ -276,19 +277,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/9b0ce92d/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 db52f40..da5233a 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 @@ -64,6 +64,7 @@ import org.apache.ignite.internal.processors.cache.CacheObject; import org.apache.ignite.internal.processors.cache.CacheObjectContext; import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor; import org.apache.ignite.internal.processors.cache.GridCacheContext; +import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManager; import org.apache.ignite.internal.processors.cache.GridCacheContextInfo; import org.apache.ignite.internal.processors.cache.KeyCacheObject; import org.apache.ignite.internal.processors.cache.QueryCursorImpl; @@ -93,7 +94,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 +106,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; @@ -1776,78 +1774,46 @@ 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>(); - - for (Map.Entry<QueryTypeIdKey, QueryTypeDescriptorImpl> e : types.entrySet()) { - if (cacheIds.contains(CU.cacheId(e.getKey().cacheName())) && - processedCacheNames.add(e.getKey().cacheName())) - fut.add(rebuildIndexesFromHash(e.getKey().cacheName(), e.getValue())); - } - - fut.markInitialized(); - - return fut; - } - finally { - busyLock.leaveBusy(); - } - } - - /** - * @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) { + public IgniteInternalFuture<?> rebuildIndexesFromHash(GridCacheContext cctx) { + // Indexing module is disabled, nothing to rebuild. if (idx == null) - return new GridFinishedFuture<>(new IgniteCheckedException("Indexing is disabled.")); - - if (desc == null) - return new GridFinishedFuture<>(); - - final GridWorkerFuture<Object> fut = new GridWorkerFuture<>(); + return null; - idx.markForRebuildFromHash(cacheName); + // No data on non-affinity nodes. + if (!cctx.affinityNode()) + return null; - GridWorker w = new GridWorker(ctx.igniteInstanceName(), "index-rebuild-worker", log) { - @Override protected void body() { - try { - idx.rebuildIndexesFromHash(cacheName); + // No indexes to rebuild when there are no QueryEntities. + if (!cctx.isQueryEnabled()) + return null; - 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); + // No need to rebuild if cache has no data. + boolean empty = true; - fut.onDone(e); + for (IgniteCacheOffheapManager.CacheDataStore store : cctx.offheap().cacheDataStores()) { + if (!store.isEmpty()) { + empty = false; - throw e; - } + break; } - }; + } - fut.setWorker(w); + if (empty) + return null; - ctx.getExecutorService().execute(w); + 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(); + } } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 ce7f4d7..11f5138 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/9b0ce92d/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java index bbdcd38..de2161a 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java @@ -96,15 +96,24 @@ public class IndexStorageSelfTest extends GridCommonAbstractTest { IndexStorageImpl metaStore = storeMap.get(cacheId); if (metaStore == null) { - metaStore = new IndexStorageImpl(mem, null, new AtomicLong(), cacheId, - PageIdAllocator.INDEX_PARTITION, PageMemory.FLAG_IDX, - null, mem.allocatePage(cacheId, PageIdAllocator.INDEX_PARTITION, PageMemory.FLAG_IDX), true, - null); + metaStore = new IndexStorageImpl( + mem, + null, + new AtomicLong(), + cacheId, + false, + PageIdAllocator.INDEX_PARTITION, + PageMemory.FLAG_IDX, + null, + mem.allocatePage(cacheId, PageIdAllocator.INDEX_PARTITION, PageMemory.FLAG_IDX), + true, + null + ); storeMap.put(cacheId, metaStore); } - final RootPage rootPage = metaStore.getOrAllocateForTree(idxName); + final RootPage rootPage = metaStore.allocateIndex(idxName); assertTrue(rootPage.isAllocated()); @@ -118,7 +127,7 @@ public class IndexStorageSelfTest extends GridCommonAbstractTest { String idxName = entry.getKey(); FullPageId rootPageId = entry.getValue().pageId(); - final RootPage rootPage = storeMap.get(cacheId).getOrAllocateForTree(idxName); + final RootPage rootPage = storeMap.get(cacheId).allocateIndex(idxName); assertEquals("Invalid root page ID restored [cacheId=" + cacheId + ", idxName=" + idxName + ']', rootPageId, rootPage.pageId()); http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 e726857..e42fc6a 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,7 @@ import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot; 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.cache.query.GridCacheQueryManager; +import org.apache.ignite.internal.processors.query.h2.affinity.PartitionInfo; 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; @@ -100,7 +101,6 @@ import org.apache.ignite.internal.processors.query.QueryIndexDescriptorImpl; import org.apache.ignite.internal.processors.query.QueryUtils; import org.apache.ignite.internal.processors.query.SqlClientContext; import org.apache.ignite.internal.processors.query.UpdateSourceIterator; -import org.apache.ignite.internal.processors.query.h2.affinity.PartitionInfo; import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory; import org.apache.ignite.internal.processors.query.h2.database.H2TreeClientIndex; import org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex; @@ -115,7 +115,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; @@ -166,6 +165,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; @@ -644,15 +645,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. @@ -2692,33 +2685,97 @@ 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; + + SchemaIndexCacheVisitorClosure 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. + IndexRebuildPartialClosure clo0 = new IndexRebuildPartialClosure(); + + for (H2TableDescriptor tblDesc : tables(cctx.name())) { + assert tblDesc.table() != null; + + tblDesc.table().collectIndexesForPartialRebuild(clo0); + } + + if (clo0.hasIndexes()) + clo = clo0; + else + return null; + } + + // Closure prepared, do rebuild. + final GridWorkerFuture<?> fut = new GridWorkerFuture<>(); + + markIndexRebuild(cctx.name(), true); + + GridWorker worker = new GridWorker(ctx.igniteInstanceName(), "index-rebuild-worker-" + cctx.name(), log) { + @Override protected void body() { + try { + rebuildIndexesFromHash0(cctx, clo); + + markIndexRebuild(cctx.name(), 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, boolean val) { for (H2TableDescriptor tblDesc : tables(cacheName)) { assert tblDesc.table() != null; - tblDesc.table().markRebuildFromHashInProgress(true); + tblDesc.table().markRebuildFromHashInProgress(val); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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..8d1923f --- /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 row0 = rowDesc.createRow(row); + + idx.putx(row0); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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..8018839 --- /dev/null +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildFullClosure.java @@ -0,0 +1,49 @@ +/* + * 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; + +/** + * Closure to rebuild all indexes. + */ +public class IndexRebuildFullClosure implements SchemaIndexCacheVisitorClosure { + /** */ + 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); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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..2672f06 --- /dev/null +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IndexRebuildPartialClosure.java @@ -0,0 +1,76 @@ +/* + * 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 org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitorClosure; + +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 SchemaIndexCacheVisitorClosure { + /** 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); + } + } + + /** + * @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/9b0ce92d/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/9b0ce92d/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java index 71cea7e..f2a69bb 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java @@ -108,8 +108,12 @@ public abstract class H2Tree extends BPlusTree<GridH2SearchRow, GridH2Row> { /** */ private final IgniteLogger log; + /** Whether PK is stored in unwrapped form. */ private boolean unwrappedPk; + /** Whether index was created from scratch during owning node lifecycle. */ + private final boolean created; + /** * Constructor. * @@ -200,6 +204,8 @@ public abstract class H2Tree extends BPlusTree<GridH2SearchRow, GridH2Row> { this.log = log; initTree(initNew, inlineSize); + + this.created = initNew; } /** @@ -556,6 +562,14 @@ public abstract class H2Tree extends BPlusTree<GridH2SearchRow, GridH2Row> { */ public abstract int compareValues(Value v1, Value v2); + /** + * @return {@code True} if index was created during curren node's lifetime, {@code False} if it was restored from + * disk. + */ + public boolean created() { + return created; + } + /** {@inheritDoc} */ @Override public String toString() { return S.toString(H2Tree.class, this, "super", super.toString()); http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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 2c0a9d8..65be8d6 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 @@ -83,6 +83,9 @@ public class H2TreeIndex extends H2TreeIndexBase { /** */ private final String idxName; + /** Tree name. */ + private final String treeName; + /** */ private final IgniteLogger log; @@ -125,14 +128,11 @@ public class H2TreeIndex extends H2TreeIndexBase { 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); @@ -152,7 +152,7 @@ public class H2TreeIndex extends H2TreeIndexBase { db.checkpointReadLock(); try { - RootPage page = getMetaPage(treeName, i); + RootPage page = getMetaPage(i); segments[i] = new H2Tree( treeName, @@ -203,6 +203,30 @@ public class H2TreeIndex extends H2TreeIndexBase { } /** + * 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 { + H2Tree segment = segments[i]; + + if (segment.created()) + 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. */ @@ -398,7 +422,7 @@ public class H2TreeIndex extends H2TreeIndexBase { tree.destroy(); - dropMetaPage(tree.getName(), i); + dropMetaPage(i); } } } @@ -493,22 +517,20 @@ public class H2TreeIndex extends H2TreeIndexBase { } /** - * @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 name Name. * @param segIdx Segment index. * @throws IgniteCheckedException If failed. */ - private void dropMetaPage(String name, int segIdx) throws IgniteCheckedException { - cctx.offheap().dropRootPageForIndex(cctx.cacheId(), name + "%" + segIdx); + private void dropMetaPage(int segIdx) throws IgniteCheckedException { + cctx.offheap().dropRootPageForIndex(cctx.cacheId(), treeName, segIdx); } /** {@inheritDoc} */ @@ -542,7 +564,7 @@ public class H2TreeIndex extends H2TreeIndexBase { * @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/9b0ce92d/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 ef31f20..59597be 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 @@ -26,7 +26,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteInterruptedException; @@ -36,7 +35,9 @@ 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.database.H2TreeIndexBase; import org.apache.ignite.internal.processors.query.h2.twostep.GridMapQueryExecutor; import org.apache.ignite.internal.util.typedef.F; @@ -89,7 +90,7 @@ public class GridH2Table extends TableBase { private final Map<String, GridH2IndexBase> tmpIdxs = new HashMap<>(); /** */ - private final ReadWriteLock lock; + private final ReentrantReadWriteLock lock; /** */ private boolean destroyed; @@ -127,6 +128,7 @@ public class GridH2Table extends TableBase { * @param idxsFactory Indexes factory. * @param cacheInfo Cache context info. */ + @SuppressWarnings("ConstantConditions") public GridH2Table(CreateTableData createTblData, GridH2RowDescriptor desc, H2RowFactory rowFactory, GridH2SystemIndexFactory idxsFactory, GridCacheContextInfo cacheInfo) { super(createTblData); @@ -175,11 +177,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(); @@ -565,12 +570,39 @@ 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); + } + } + } + + /** + * Mark or unmark index rebuild state. */ public void markRebuildFromHashInProgress(boolean value) { assert !value || (idxs.size() >= 2 && index(1).getIndexType().isHash()) : "Table has no hash index."; rebuildFromHashInProgress = value; + + lock.writeLock().lock(); + + try { + incrementModificationCounter(); + } + finally { + lock.writeLock().unlock(); + } } /** @@ -651,7 +683,7 @@ public class GridH2Table extends TableBase { if (cloneIdx != null) database.addSchemaObject(ses, cloneIdx); - setModified(); + incrementModificationCounter(); return idx; } @@ -955,7 +987,7 @@ public class GridH2Table extends TableBase { desc.refreshMetadataFromTypeDescriptor(); - setModified(); + incrementModificationCounter(); } finally { unlock(true); @@ -963,9 +995,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; @@ -1017,7 +1050,7 @@ public class GridH2Table extends TableBase { ((GridH2IndexBase)idx).refreshColumnIds(); } - setModified(); + incrementModificationCounter(); } finally { unlock(true); @@ -1046,6 +1079,15 @@ public class GridH2Table extends TableBase { } /** + * Increment modification counter to force recompilation of existing prepared statements. + */ + private void incrementModificationCounter() { + assert lock.isWriteLockedByCurrentThread(); + + setModified(); + } + + /** * Set insert hack flag. * * @param val Value. http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicSqlRestoreTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicSqlRestoreTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicSqlRestoreTest.java index f7dc7b4..d009f33 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicSqlRestoreTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicSqlRestoreTest.java @@ -18,12 +18,20 @@ package org.apache.ignite.internal.processors.cache; import java.io.Serializable; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.Timestamp; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; +import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteDataStreamer; +import org.apache.ignite.Ignition; import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.cache.QueryEntity; import org.apache.ignite.cache.query.SqlFieldsQuery; @@ -33,8 +41,10 @@ import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.WALMode; import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.util.typedef.PA; import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.spi.IgniteSpiException; +import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.jetbrains.annotations.NotNull; @@ -44,6 +54,7 @@ import static org.hamcrest.MatcherAssert.assertThat; /** * */ +@SuppressWarnings("Duplicates") public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implements Serializable { public static final String TEST_CACHE_NAME = "test"; @@ -117,7 +128,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen //and: change data try (IgniteDataStreamer<Object, Object> s = ig.dataStreamer(TEST_CACHE_NAME)) { s.allowOverwrite(true); - for (int i = 0; i < 5_000; i++) + for (int i = 0; i < 50; i++) s.addData(i, null); } @@ -134,7 +145,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen //then: everything is ok try (IgniteDataStreamer<Object, Object> s = ig1.dataStreamer(TEST_CACHE_NAME)) { s.allowOverwrite(true); - for (int i = 0; i < 50_000; i++) { + for (int i = 0; i < 50; i++) { BinaryObject bo = ig1.binary().builder(TEST_INDEX_OBJECT) .setField("a", i, Object.class) .setField("b", String.valueOf(i), Object.class) @@ -147,12 +158,132 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen IgniteCache<Object, Object> cache = ig1.cache(TEST_CACHE_NAME); - assertThat(doExplainPlan(cache, "explain select * from TestIndexObject where a > 5"), containsString("myindexa")); + assertIndexUsed(cache, "explain select * from TestIndexObject where a > 5", "myindexa"); assertFalse(cache.query(new SqlFieldsQuery("SELECT a,b,c FROM TestIndexObject limit 1")).getAll().isEmpty()); } } /** + * @throws Exception If failed. + */ + @SuppressWarnings("AssertWithSideEffects") + public void testIndexCreationWhenNodeStopped() throws Exception { + // Start topology. + startGrid(0); + Ignite srv2 = startGrid(1); + Ignite cli; + + Ignition.setClientMode(true); + + try { + cli = startGrid(2); + } + finally { + Ignition.setClientMode(false); + } + + cli.cluster().active(true); + + // Create table, add some data. + int entryCnt = 50; + + try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:10802")) { + executeJdbc(conn, + " CREATE TABLE PERSON (\n" + + " FIRST_NAME VARCHAR,\n" + + " LAST_NAME VARCHAR,\n" + + " ADDRESS VARCHAR,\n" + + " LANG VARCHAR,\n" + + " BIRTH_DATE TIMESTAMP,\n" + + " CONSTRAINT PK_PESON PRIMARY KEY (FIRST_NAME,LAST_NAME,ADDRESS,LANG)\n" + + " ) WITH \"key_type=PersonKeyType, CACHE_NAME=PersonCache, value_type=PersonValueType, AFFINITY_KEY=FIRST_NAME,template=PARTITIONED,backups=1\""); + + try (PreparedStatement stmt = conn.prepareStatement( + "insert into Person(LANG, FIRST_NAME, ADDRESS, LAST_NAME, BIRTH_DATE) values(?,?,?,?,?)")) { + for (int i = 0; i < entryCnt; i++) { + String s = String.valueOf(i); + + stmt.setString(1, s); + stmt.setString(2, s); + stmt.setString(3, s); + stmt.setString(4, s); + stmt.setTimestamp(5, new Timestamp(System.currentTimeMillis())); + + stmt.executeUpdate(); + } + } + } + + // Stop second node. + srv2.close(); + + // Create an index on remaining node. + try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:10802")) { + executeJdbc(conn, "create index PERSON_FIRST_NAME_IDX on PERSON(FIRST_NAME)"); + } + + // Restart second node. + startGrid(1); + + // Await for index rebuild on started node. + assert GridTestUtils.waitForCondition(new PA() { + @Override public boolean apply() { + try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:10801")) { + try (PreparedStatement stmt = conn.prepareStatement( + "EXPLAIN SELECT * FROM Person USE INDEX(PERSON_FIRST_NAME_IDX) WHERE FIRST_NAME=?")) { + stmt.setString(1, String.valueOf(1)); + + StringBuilder fullPlan = new StringBuilder(); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) + fullPlan.append(rs.getString(1)).append("; "); + } + + System.out.println("PLAN: " + fullPlan); + + return fullPlan.toString().contains("PUBLIC.PERSON_FIRST_NAME_IDX"); + } + } + catch (Exception e) { + throw new RuntimeException("Query failed.", e); + } + } + }, 5_000); + + // Make sure that data could be queried. + try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:10802")) { + try (PreparedStatement stmt = conn.prepareStatement( + "SELECT COUNT(*) FROM Person USE INDEX(PERSON_FIRST_NAME_IDX) WHERE FIRST_NAME=?")) { + for (int i = 0; i < entryCnt; i ++) { + stmt.setString(1, String.valueOf(i)); + + try (ResultSet rs = stmt.executeQuery()) { + rs.next(); + + long cnt = rs.getLong(1); + + assertEquals(1L, cnt); + } + } + } + } + } + + /** + * Execute a statement through JDBC connection. + * + * @param conn Connection. + * @param sql Statement. + * @throws Exception If failed. + */ + private static void executeJdbc(Connection conn, String sql) throws Exception { + try (Statement stmt = conn.createStatement()) { + stmt.execute(sql); + } + } + + /** * @throws Exception if failed. */ public void testTakeConfigFromJoiningNodeOnInactiveGrid() throws Exception { @@ -186,7 +317,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen //then: config for cache was applying successful IgniteCache<Object, Object> cache = ig.cache(TEST_CACHE_NAME); - assertThat(doExplainPlan(cache, "explain select * from TestIndexObject where a > 5"), containsString("myindexa")); + assertIndexUsed(cache, "explain select * from TestIndexObject where a > 5", "myindexa"); assertFalse(cache.query(new SqlFieldsQuery("SELECT a,b,c FROM TestIndexObject limit 1")).getAll().isEmpty()); } } @@ -233,7 +364,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen IgniteCache<Object, Object> cache = ig.cache(TEST_CACHE_NAME); - assertThat(doExplainPlan(cache, "explain select * from TestIndexObject where a > 5"), containsString("myindexa")); + assertIndexUsed(cache, "explain select * from TestIndexObject where a > 5", "myindexa"); assertFalse(cache.query(new SqlFieldsQuery("SELECT a,b,c FROM TestIndexObject limit 1")).getAll().isEmpty()); } } @@ -241,6 +372,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen /** * @throws Exception if failed. */ + @SuppressWarnings("ArraysAsListWithZeroOrOneArgument") public void testMergeChangedConfigOnInactiveGrid() throws Exception { { //given: two started nodes with test table @@ -288,7 +420,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen //then: config should be merged try (IgniteDataStreamer<Object, Object> s = ig1.dataStreamer(TEST_CACHE_NAME)) { s.allowOverwrite(true); - for (int i = 0; i < 5_000; i++) { + for (int i = 0; i < 50; i++) { BinaryObject bo = ig1.binary().builder("TestIndexObject") .setField("a", i, Object.class) .setField("b", String.valueOf(i), Object.class) @@ -300,13 +432,32 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen IgniteCache<Object, Object> cache = ig1.cache(TEST_CACHE_NAME); //then: index "myindexa" and column "b" restored from node "1" - assertThat(doExplainPlan(cache, "explain select * from TestIndexObject where a > 5"), containsString("myindexa")); - assertThat(doExplainPlan(cache, "explain select * from TestIndexObject where b > 5"), containsString("myindexb")); + assertIndexUsed(cache, "explain select * from TestIndexObject where a > 5", "myindexa"); + assertIndexUsed(cache, "explain select * from TestIndexObject where b > 5", "myindexb"); assertFalse(cache.query(new SqlFieldsQuery("SELECT a,b FROM TestIndexObject limit 1")).getAll().isEmpty()); } } /** + * Make sure that index is used for the given statement. + * + * @param cache Cache. + * @param sql Statement. + * @param idx Index. + * @throws IgniteCheckedException If failed. + */ + private void assertIndexUsed(IgniteCache<Object, Object> cache, String sql, String idx) + throws IgniteCheckedException { + assert GridTestUtils.waitForCondition(new PA() { + @Override public boolean apply() { + String plan = doExplainPlan(cache, sql); + + return plan.contains(idx); + } + }, 10_000); + } + + /** * @throws Exception if failed. */ public void testTakeChangedConfigOnActiveGrid() throws Exception { @@ -341,7 +492,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen //then: config should be merged try (IgniteDataStreamer<Object, Object> s = ig.dataStreamer(TEST_CACHE_NAME)) { s.allowOverwrite(true); - for (int i = 0; i < 5_000; i++) { + for (int i = 0; i < 50; i++) { BinaryObject bo = ig.binary().builder("TestIndexObject") .setField("a", i, Object.class) .setField("b", String.valueOf(i), Object.class) @@ -355,7 +506,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen cache.indexReadyFuture().get(); - assertThat(doExplainPlan(cache, "explain select * from TestIndexObject where a > 5"), containsString("myindexa")); + assertIndexUsed(cache, "explain select * from TestIndexObject where a > 5", "myindexa"); assertFalse(cache.query(new SqlFieldsQuery("SELECT a,b,c FROM TestIndexObject limit 1")).getAll().isEmpty()); } } @@ -363,6 +514,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen /** * @throws Exception if failed. */ + @SuppressWarnings("ConstantConditions") public void testFailJoiningNodeBecauseDifferentSql() throws Exception { { //given: two started nodes with test table @@ -407,6 +559,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen /** * @throws Exception if failed. */ + @SuppressWarnings("ConstantConditions") public void testFailJoiningNodeBecauseFieldInlineSizeIsDifferent() throws Exception { { //given: two started nodes with test table @@ -417,13 +570,13 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen IgniteCache cache = ig.getOrCreateCache(getTestTableConfiguration()); - cache.query(new SqlFieldsQuery("create index myindexa on TestIndexObject(a) INLINE_SIZE 1000")).getAll(); + cache.query(new SqlFieldsQuery("create index myindexa on TestIndexObject(a) INLINE_SIZE 100")).getAll(); //stop one node and create index on other node stopGrid(1); cache.query(new SqlFieldsQuery("drop index myindexa")).getAll(); - cache.query(new SqlFieldsQuery("create index myindexa on TestIndexObject(a) INLINE_SIZE 2000")).getAll(); + cache.query(new SqlFieldsQuery("create index myindexa on TestIndexObject(a) INLINE_SIZE 200")).getAll(); //and: stopped all grid stopAllGrids(); @@ -447,6 +600,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen /** * @throws Exception if failed. */ + @SuppressWarnings("ConstantConditions") public void testFailJoiningNodeBecauseNeedConfigUpdateOnActiveGrid() throws Exception { { startGrid(0); @@ -497,7 +651,7 @@ public class IgniteDynamicSqlRestoreTest extends GridCommonAbstractTest implemen */ private void fillTestData(Ignite ig) { try (IgniteDataStreamer<Object, Object> s = ig.dataStreamer(TEST_CACHE_NAME)) { - for (int i = 0; i < 50_000; i++) { + for (int i = 0; i < 500; i++) { BinaryObject bo = ig.binary().builder("TestIndexObject") .setField("a", i, Object.class) .setField("b", String.valueOf(i), Object.class) http://git-wip-us.apache.org/repos/asf/ignite/blob/9b0ce92d/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..d8ba060 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; @@ -38,7 +40,7 @@ import org.apache.ignite.internal.util.typedef.internal.U; */ public class GridIndexRebuildSelfTest extends DynamicIndexAbstractSelfTest { /** Data size. */ - protected static final int AMOUNT = 300; + protected static final int AMOUNT = 50; /** Data size. */ protected static final String CACHE_NAME = "T"; @@ -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); } } }