Repository: ignite Updated Branches: refs/heads/ignite-9720 [created] 057f4fdc7
ignite-9720 Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/057f4fdc Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/057f4fdc Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/057f4fdc Branch: refs/heads/ignite-9720 Commit: 057f4fdc7ede35779e98b09a7e9c7a7844f3d70e Parents: 82d2efe Author: sboikov <sboi...@apache.org> Authored: Fri Oct 19 15:39:22 2018 +0300 Committer: sboikov <sboi...@apache.org> Committed: Fri Oct 19 15:39:22 2018 +0300 ---------------------------------------------------------------------- .../cache/persistence/CacheFreeList.java | 32 ++++ .../persistence/GridCacheOffheapManager.java | 64 +++++-- .../IgniteCacheDatabaseSharedManager.java | 26 +-- .../cache/persistence/LazyCacheFreeList.java | 168 +++++++++++++++++++ .../persistence/freelist/AbstractFreeList.java | 9 +- .../cache/persistence/freelist/FreeList.java | 13 ++ .../cache/persistence/freelist/PagesList.java | 4 +- 7 files changed, 276 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/057f4fdc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheFreeList.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheFreeList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheFreeList.java new file mode 100644 index 0000000..2d79cd6 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheFreeList.java @@ -0,0 +1,32 @@ +/* + * 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.cache.persistence; + +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList; +import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList; + +/** + * + */ +public interface CacheFreeList<T extends Storable> extends FreeList<T>, ReuseList { + /** + * @throws IgniteCheckedException If failed. + */ + public void saveMetadata() throws IgniteCheckedException; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/057f4fdc/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 cb682f6..22249cd 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 @@ -65,6 +65,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.topology.Grid import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot; import org.apache.ignite.internal.processors.cache.mvcc.MvccVersion; import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeListImpl; +import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList; import org.apache.ignite.internal.processors.cache.persistence.migration.UpgradePendingTreeToPerPartitionTask; import org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMemoryEx; import org.apache.ignite.internal.processors.cache.persistence.partstate.GroupPartitionId; @@ -246,7 +247,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple RowStore rowStore0 = store.rowStore(); if (rowStore0 != null) { - CacheFreeListImpl freeList = (CacheFreeListImpl)rowStore0.freeList(); + CacheFreeList freeList = (CacheFreeList)rowStore0.freeList(); freeList.saveMetadata(); @@ -880,7 +881,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple for (CacheDataStore store : partDataStores.values()) { assert store instanceof GridCacheDataStore; - CacheFreeListImpl freeList = ((GridCacheDataStore)store).freeList; + FreeList<CacheDataRow> freeList = ((GridCacheDataStore)store).freeList; if (freeList == null) continue; @@ -1263,6 +1264,44 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple /** * */ + private static class PartitionCacheFreeList extends CacheFreeListImpl { + /** */ + private final CacheGroupContext grp; + + /** */ + private final int partId; + + /** + * @param grp Cache group. + * @param partId Partition. + * @param reuseRoot Reuse list root page. + * @throws IgniteCheckedException If failed. + */ + PartitionCacheFreeList(CacheGroupContext grp, int partId, RootPage reuseRoot) throws IgniteCheckedException { + super(grp.groupId(), + grp.cacheOrGroupName() + "-" + partId, + grp.dataRegion().memoryMetrics(), + grp.dataRegion(), + null, + grp.shared().wal(), + reuseRoot.pageId().pageId(), + reuseRoot.isAllocated()); + + this.grp = grp; + this.partId = partId; + } + + /** {@inheritDoc} */ + @Override protected long allocatePageNoReuse() throws IgniteCheckedException { + assert grp.shared().database().checkpointLockIsHeldByThread(); + + return pageMem.allocatePage(grpId, partId, PageIdAllocator.FLAG_DATA); + } + } + + /** + * + */ public class GridCacheDataStore implements CacheDataStore { /** */ private final int partId; @@ -1271,7 +1310,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple private String name; /** */ - private volatile CacheFreeListImpl freeList; + private volatile CacheFreeList freeList; /** */ private PendingEntriesTree pendingTree; @@ -1318,7 +1357,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple return null; } - if (init.compareAndSet(false, true)) { + if (!init.get() && init.compareAndSet(false, true)) { IgniteCacheDatabaseSharedManager dbMgr = ctx.database(); dbMgr.checkpointReadLock(); @@ -1328,20 +1367,9 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple RootPage reuseRoot = metas.reuseListRoot; - freeList = new CacheFreeListImpl( - grp.groupId(), - grp.cacheOrGroupName() + "-" + partId, - grp.dataRegion().memoryMetrics(), - grp.dataRegion(), - null, - ctx.wal(), - reuseRoot.pageId().pageId(), - reuseRoot.isAllocated()) { - /** {@inheritDoc} */ - @Override protected long allocatePageNoReuse() throws IgniteCheckedException { - assert grp.shared().database().checkpointLockIsHeldByThread(); - - return pageMem.allocatePage(grpId, partId, PageIdAllocator.FLAG_DATA); + freeList = new LazyCacheFreeList() { + @Override protected CacheFreeList createDelegate() throws IgniteCheckedException { + return new PartitionCacheFreeList(grp, partId, reuseRoot); } }; http://git-wip-us.apache.org/repos/asf/ignite/blob/057f4fdc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java index 28ce085..d146f43 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java @@ -106,10 +106,10 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap protected DataRegion dfltDataRegion; /** */ - protected Map<String, CacheFreeListImpl> freeListMap; + protected Map<String, CacheFreeList> freeListMap; /** */ - private CacheFreeListImpl dfltFreeList; + private CacheFreeList dfltFreeList; /** Page size from memory configuration, may be set only for fake(standalone) IgniteCacheDataBaseSharedManager */ private int pageSize; @@ -195,13 +195,13 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap boolean persistenceEnabled = memPlcCfg.isPersistenceEnabled(); CacheFreeListImpl freeList = new CacheFreeListImpl(0, - cctx.igniteInstanceName(), - memMetrics, - memPlc, - null, - persistenceEnabled ? cctx.wal() : null, - 0L, - true); + cctx.igniteInstanceName(), + memMetrics, + memPlc, + null, + persistenceEnabled ? cctx.wal() : null, + 0L, + true); freeListMap.put(memPlcCfg.getName(), freeList); } @@ -328,11 +328,11 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap final String dataRegName = dataRegCfg.getName(); return new IgniteOutClosure<Long>() { - private CacheFreeListImpl freeList; + private CacheFreeList freeList; @Override public Long apply() { if (freeList == null) { - CacheFreeListImpl freeList0 = freeListMap.get(dataRegName); + CacheFreeList freeList0 = freeListMap.get(dataRegName); if (freeList0 == null) return 0L; @@ -611,7 +611,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap */ public void dumpStatistics(IgniteLogger log) { if (freeListMap != null) { - for (CacheFreeListImpl freeList : freeListMap.values()) + for (CacheFreeList freeList : freeListMap.values()) freeList.dumpStatistics(log); } } @@ -922,7 +922,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap int sysPageSize = pageMem.systemPageSize(); - CacheFreeListImpl freeListImpl = freeListMap.get(plcCfg.getName()); + CacheFreeList freeListImpl = freeListMap.get(plcCfg.getName()); for (;;) { long allocatedPagesCnt = pageMem.loadedPages(); http://git-wip-us.apache.org/repos/asf/ignite/blob/057f4fdc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/LazyCacheFreeList.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/LazyCacheFreeList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/LazyCacheFreeList.java new file mode 100644 index 0000000..1cbd841 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/LazyCacheFreeList.java @@ -0,0 +1,168 @@ +/* + * 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.cache.persistence; + +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.IgniteLogger; +import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseBag; +import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler; +import org.apache.ignite.internal.util.typedef.internal.U; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +/** + * + */ +public abstract class LazyCacheFreeList implements CacheFreeList<CacheDataRow> { + /** */ + private static final AtomicReferenceFieldUpdater<LazyCacheFreeList, CountDownLatch> initLatchUpdater = + AtomicReferenceFieldUpdater.newUpdater(LazyCacheFreeList.class, CountDownLatch.class, "initLatch"); + + /** */ + private volatile CacheFreeList delegate; + + /** */ + private IgniteCheckedException initErr; + + /** */ + private volatile CountDownLatch initLatch; + + /** {@inheritDoc} */ + @Override public void saveMetadata() throws IgniteCheckedException { + CacheFreeList delegate = this.delegate; + + if (delegate != null) + delegate.saveMetadata(); + } + + /** {@inheritDoc} */ + @Override public void insertDataRow(CacheDataRow row) throws IgniteCheckedException { + initDelegateIfNeeded().insertDataRow(row); + } + + /** {@inheritDoc} */ + @Override public boolean updateDataRow(long link, CacheDataRow row) throws IgniteCheckedException { + return initDelegateIfNeeded().updateDataRow(link, row); + } + + /** {@inheritDoc} */ + @Override public <S, R> R updateDataRow(long link, PageHandler<S, R> pageHnd, S arg) throws IgniteCheckedException { + return (R)initDelegateIfNeeded().updateDataRow(link, pageHnd, arg); + } + + /** {@inheritDoc} */ + @Override public void removeDataRowByLink(long link) throws IgniteCheckedException { + initDelegateIfNeeded().removeDataRowByLink(link); + } + + /** {@inheritDoc} */ + @Override public int emptyDataPages() { + try { + return initDelegateIfNeeded().emptyDataPages(); + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to initialize FreeList", e); + } + } + + /** {@inheritDoc} */ + @Override public long freeSpace() { + try { + return initDelegateIfNeeded().freeSpace(); + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to initialize FreeList", e); + } + } + + /** {@inheritDoc} */ + @Override public void dumpStatistics(IgniteLogger log) { + CacheFreeList delegate = this.delegate; + + if (delegate != null) + delegate.dumpStatistics(log); + } + + /** {@inheritDoc} */ + @Override public void addForRecycle(ReuseBag bag) throws IgniteCheckedException { + initDelegateIfNeeded().addForRecycle(bag); + } + + /** {@inheritDoc} */ + @Override public long takeRecycledPage() throws IgniteCheckedException { + return initDelegateIfNeeded().takeRecycledPage(); + } + + /** {@inheritDoc} */ + @Override public long recycledPagesCount() throws IgniteCheckedException { + return initDelegateIfNeeded().recycledPagesCount(); + } + + /** + * @return Cache free list. + * @throws IgniteCheckedException If failed. + */ + protected abstract CacheFreeList createDelegate() throws IgniteCheckedException; + + /** + * @return Cache free list. + * @throws IgniteCheckedException If failed to initialize free list. + */ + private CacheFreeList initDelegateIfNeeded() throws IgniteCheckedException { + CacheFreeList delegate = this.delegate; + + if (delegate != null) + return delegate; + + CountDownLatch initLatch = this.initLatch; + + if (initLatch != null) + U.await(initLatch); + else { + initLatch = new CountDownLatch(1); + + if (initLatchUpdater.compareAndSet(this, null, initLatch)) { + try { + this.delegate = createDelegate(); + } + catch (IgniteCheckedException e) { + this.initErr = e; + } + finally { + initLatch.countDown(); + } + } + else { + initLatch = this.initLatch; + + assert initLatch != null; + + U.await(initLatch); + } + } + + IgniteCheckedException initErr = this.initErr; + + if (initErr != null) + throw initErr; + + return this.delegate; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/057f4fdc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java index 4e1f783..b446ccb 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java @@ -28,6 +28,7 @@ import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertFragmen import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertRecord; import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageRemoveRecord; import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageUpdateRecord; +import org.apache.ignite.internal.processors.cache.persistence.CacheFreeList; import org.apache.ignite.internal.processors.cache.persistence.DataRegion; import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl; import org.apache.ignite.internal.processors.cache.persistence.Storable; @@ -44,7 +45,7 @@ import org.apache.ignite.internal.util.typedef.internal.U; /** */ -public abstract class AbstractFreeList<T extends Storable> extends PagesList implements FreeList<T>, ReuseList { +public abstract class AbstractFreeList<T extends Storable> extends PagesList implements CacheFreeList<T> { /** */ private static final int BUCKETS = 256; // Must be power of 2. @@ -371,11 +372,7 @@ public abstract class AbstractFreeList<T extends Storable> extends PagesList imp init(metaPageId, initNew); } - /** - * Calculates free space tracked by this FreeListImpl instance. - * - * @return Free space available for use, in bytes. - */ + /** {@inheritDoc} */ public long freeSpace() { long freeSpace = 0; http://git-wip-us.apache.org/repos/asf/ignite/blob/057f4fdc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/FreeList.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/FreeList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/FreeList.java index e73124e..29e8400 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/FreeList.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/FreeList.java @@ -23,6 +23,7 @@ import org.apache.ignite.internal.processors.cache.persistence.Storable; import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler; /** + * */ public interface FreeList<T extends Storable> { /** @@ -57,6 +58,18 @@ public interface FreeList<T extends Storable> { public void removeDataRowByLink(long link) throws IgniteCheckedException; /** + * @return Number of empty data pages in free list. + */ + public int emptyDataPages(); + + /** + * Calculates free space tracked by this free list. + * + * @return Free space available for use, in bytes. + */ + public long freeSpace(); + + /** * @param log Logger. */ public void dumpStatistics(IgniteLogger log); http://git-wip-us.apache.org/repos/asf/ignite/blob/057f4fdc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java index f1cc32a..e08439d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java @@ -251,9 +251,7 @@ public abstract class PagesList extends DataStructure { } } - /** - * @throws IgniteCheckedException If failed. - */ + /** {@inheritDoc} */ public void saveMetadata() throws IgniteCheckedException { assert metaPageId != 0;