You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/06/11 20:04:03 UTC
[37/47] ignite git commit: IGNITE-5267 - Moved ignite-ps module to
ignite-core
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheSnapshotManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheSnapshotManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheSnapshotManager.java
new file mode 100644
index 0000000..e490e35
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheSnapshotManager.java
@@ -0,0 +1,133 @@
+/*
+ * 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 java.nio.ByteBuffer;
+import java.util.NavigableMap;
+import java.util.UUID;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.pagemem.snapshot.SnapshotOperation;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedManagerAdapter;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class IgniteCacheSnapshotManager extends GridCacheSharedManagerAdapter {
+ /** Snapshot started lock filename. */
+ public static final String SNAPSHOT_RESTORE_STARTED_LOCK_FILENAME = "snapshot-started.loc";
+
+ /**
+ * @param initiatorNodeId Initiator node id.
+ * @param snapshotOperation Snapshot operation.
+ */
+ @Nullable public IgniteInternalFuture startLocalSnapshotOperation(
+ UUID initiatorNodeId,
+ SnapshotOperation snapshotOperation
+ ) throws IgniteCheckedException {
+ return null;
+ }
+
+ /**
+ * @param snapOp current snapshot operation.
+ *
+ * @return {@code true} if next operation must be snapshot, {@code false} if checkpoint must be executed.
+ */
+ public boolean onMarkCheckPointBegin(
+ SnapshotOperation snapOp,
+ NavigableMap<T2<Integer, Integer>, T2<Integer, Integer>> map
+ ) throws IgniteCheckedException {
+ return false;
+ }
+
+ /**
+ *
+ */
+ public void restoreState() throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /**
+ *
+ */
+ public void onCheckPointBegin() {
+ // No-op.
+ }
+
+ /**
+ *
+ */
+ public void beforeCheckpointPageWritten() {
+ // No-op.
+ }
+
+ /**
+ *
+ */
+ public void afterCheckpointPageWritten() {
+ // No-op.
+ }
+
+ /**
+ * @param fullId Full id.
+ */
+ public void beforePageWrite(FullPageId fullId) {
+ // No-op.
+ }
+
+ /**
+ * @param fullId Full id.
+ */
+ public void onPageWrite(FullPageId fullId, ByteBuffer tmpWriteBuf) {
+ // No-op.
+ }
+
+ /**
+ * @param cctx Cctx.
+ */
+ public void onCacheStop(GridCacheContext cctx) {
+ // No-op.
+ }
+
+ /**
+ *
+ */
+ public void onChangeTrackerPage(
+ Long page,
+ FullPageId fullId,
+ PageMemory pageMem
+ ) throws IgniteCheckedException {
+
+ }
+
+ /**
+ *
+ */
+ public void flushDirtyPageHandler(
+ FullPageId fullId,
+ ByteBuffer pageBuf,
+ Integer tag
+ ) throws IgniteCheckedException {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsImpl.java
new file mode 100644
index 0000000..271767c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsImpl.java
@@ -0,0 +1,284 @@
+/*
+ * 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.MemoryMetrics;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeListImpl;
+import org.apache.ignite.internal.processors.cache.ratemetrics.HitRateMetrics;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jsr166.LongAdder8;
+
+/**
+ *
+ */
+public class MemoryMetricsImpl implements MemoryMetrics {
+ /** */
+ private FreeListImpl freeList;
+
+ /** */
+ private final LongAdder8 totalAllocatedPages = new LongAdder8();
+
+ /**
+ * Counter for number of pages occupied by large entries (one entry is larger than one page).
+ */
+ private final LongAdder8 largeEntriesPages = new LongAdder8();
+
+ /** Counter for number of dirty pages. */
+ private LongAdder8 dirtyPages = new LongAdder8();
+
+ /** */
+ private volatile boolean metricsEnabled;
+
+ /** */
+ private boolean persistenceEnabled;
+
+ /** */
+ private volatile int subInts;
+
+ /** Allocation rate calculator. */
+ private volatile HitRateMetrics allocRate = new HitRateMetrics(60_000, 5);
+
+ /** */
+ private volatile HitRateMetrics pageReplaceRate = new HitRateMetrics(60_000, 5);
+
+ /** */
+ private final MemoryPolicyConfiguration memPlcCfg;
+
+ /** */
+ private PageMemory pageMem;
+
+ /** Time interval (in milliseconds) when allocations/evictions are counted to calculate rate. */
+ private volatile long rateTimeInterval;
+
+ /**
+ * @param memPlcCfg MemoryPolicyConfiguration.
+ */
+ public MemoryMetricsImpl(MemoryPolicyConfiguration memPlcCfg) {
+ this.memPlcCfg = memPlcCfg;
+
+ metricsEnabled = memPlcCfg.isMetricsEnabled();
+
+ rateTimeInterval = memPlcCfg.getRateTimeInterval();
+
+ subInts = memPlcCfg.getSubIntervals();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getName() {
+ return U.maskName(memPlcCfg.getName());
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getTotalAllocatedPages() {
+ return metricsEnabled ? totalAllocatedPages.longValue() : 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getAllocationRate() {
+ if (!metricsEnabled)
+ return 0;
+
+ return ((float) allocRate.getRate()) / rateTimeInterval;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getEvictionRate() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getLargeEntriesPagesPercentage() {
+ if (!metricsEnabled)
+ return 0;
+
+ return totalAllocatedPages.longValue() != 0 ?
+ (float) largeEntriesPages.doubleValue() / totalAllocatedPages.longValue()
+ : 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getPagesFillFactor() {
+ if (!metricsEnabled || freeList == null)
+ return 0;
+
+ return freeList.fillFactor();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDirtyPages() {
+ if (!metricsEnabled || !persistenceEnabled)
+ return 0;
+
+ return dirtyPages.longValue();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getPagesReplaceRate() {
+ if (!metricsEnabled || !persistenceEnabled)
+ return 0;
+
+ return ((float) pageReplaceRate.getRate()) / rateTimeInterval;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getPhysicalMemoryPages() {
+ if (!metricsEnabled || !persistenceEnabled)
+ return 0;
+
+ assert pageMem != null;
+
+ return pageMem.loadedPages();
+ }
+
+ /**
+ * Updates pageReplaceRate metric.
+ */
+ public void updatePageReplaceRate() {
+ if (metricsEnabled)
+ pageReplaceRate.onHit();
+ }
+
+ /**
+ * Increments dirtyPages counter.
+ */
+ public void incrementDirtyPages() {
+ if (metricsEnabled)
+ dirtyPages.increment();
+ }
+
+ /**
+ * Decrements dirtyPages counter.
+ */
+ public void decrementDirtyPages() {
+ if (metricsEnabled)
+ dirtyPages.decrement();
+ }
+
+ /**
+ * Resets dirtyPages counter to zero.
+ */
+ public void resetDirtyPages() {
+ if (metricsEnabled)
+ dirtyPages.reset();
+ }
+
+ /**
+ * Increments totalAllocatedPages counter.
+ */
+ public void incrementTotalAllocatedPages() {
+ if (metricsEnabled) {
+ totalAllocatedPages.increment();
+
+ updateAllocationRateMetrics();
+ }
+ }
+
+ /**
+ *
+ */
+ private void updateAllocationRateMetrics() {
+ allocRate.onHit();
+ }
+
+ /**
+ * @param intervalNum Interval number.
+ */
+ private long subInt(int intervalNum) {
+ return (rateTimeInterval * intervalNum) / subInts;
+ }
+
+ /**
+ *
+ */
+ public void incrementLargeEntriesPages() {
+ if (metricsEnabled)
+ largeEntriesPages.increment();
+ }
+
+ /**
+ *
+ */
+ public void decrementLargeEntriesPages() {
+ if (metricsEnabled)
+ largeEntriesPages.decrement();
+ }
+
+ /**
+ * Enable metrics.
+ */
+ public void enableMetrics() {
+ metricsEnabled = true;
+ }
+
+ /**
+ * Disable metrics.
+ */
+ public void disableMetrics() {
+ metricsEnabled = false;
+ }
+
+ /**
+ * @param persistenceEnabled Persistence enabled.
+ */
+ public void persistenceEnabled(boolean persistenceEnabled) {
+ this.persistenceEnabled = persistenceEnabled;
+ }
+
+ /**
+ * @param pageMem Page mem.
+ */
+ public void pageMemory(PageMemory pageMem) {
+ this.pageMem = pageMem;
+ }
+
+ /**
+ * @param rateTimeInterval Time interval (in milliseconds) used to calculate allocation/eviction rate.
+ */
+ public void rateTimeInterval(long rateTimeInterval) {
+ this.rateTimeInterval = rateTimeInterval;
+
+ allocRate = new HitRateMetrics((int) rateTimeInterval, subInts);
+ pageReplaceRate = new HitRateMetrics((int) rateTimeInterval, subInts);
+ }
+
+ /**
+ * Sets number of subintervals the whole rateTimeInterval will be split into to calculate allocation rate.
+ *
+ * @param subInts Number of subintervals.
+ */
+ public void subIntervals(int subInts) {
+ assert subInts > 0;
+
+ if (this.subInts == subInts)
+ return;
+
+ if (rateTimeInterval / subInts < 10)
+ subInts = (int) rateTimeInterval / 10;
+
+ allocRate = new HitRateMetrics((int) rateTimeInterval, subInts);
+ pageReplaceRate = new HitRateMetrics((int) rateTimeInterval, subInts);
+ }
+
+ /**
+ * @param freeList Free list.
+ */
+ void freeList(FreeListImpl freeList) {
+ this.freeList = freeList;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsMXBeanImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsMXBeanImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsMXBeanImpl.java
new file mode 100644
index 0000000..392f83f
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsMXBeanImpl.java
@@ -0,0 +1,131 @@
+/*
+ * 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.MemoryMetrics;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.mxbean.MemoryMetricsMXBean;
+
+/**
+ * MBean to expose {@link MemoryMetrics} through JMX interface.
+ */
+class MemoryMetricsMXBeanImpl implements MemoryMetricsMXBean {
+ /** */
+ private final MemoryMetricsImpl memMetrics;
+
+ /** */
+ private final MemoryPolicyConfiguration memPlcCfg;
+
+ /**
+ * @param memMetrics MemoryMetrics instance to expose through JMX interface.
+ * @param memPlcCfg configuration of memory policy this MX Bean is created for.
+ */
+ MemoryMetricsMXBeanImpl(MemoryMetricsImpl memMetrics,
+ MemoryPolicyConfiguration memPlcCfg
+ ) {
+ this.memMetrics = memMetrics;
+ this.memPlcCfg = memPlcCfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getAllocationRate() {
+ return memMetrics.getAllocationRate();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getEvictionRate() {
+ return memMetrics.getEvictionRate();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getLargeEntriesPagesPercentage() {
+ return memMetrics.getLargeEntriesPagesPercentage();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getPagesFillFactor() {
+ return memMetrics.getPagesFillFactor();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getTotalAllocatedPages() {
+ return memMetrics.getTotalAllocatedPages();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDirtyPages() {
+ return memMetrics.getDirtyPages();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getPagesReplaceRate() {
+ return memMetrics.getPagesReplaceRate();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getPhysicalMemoryPages() {
+ return memMetrics.getPhysicalMemoryPages();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void rateTimeInterval(long rateTimeInterval) {
+ if (rateTimeInterval < 1000)
+ throw new IllegalArgumentException("rateTimeInterval property must be positive " +
+ "and greater than 1_000 milliseconds (one second)");
+
+ memMetrics.rateTimeInterval(rateTimeInterval);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void subIntervals(int subInts) {
+ if (subInts <= 1)
+ throw new IllegalArgumentException("subIntervals property must be positive " +
+ "and greater than one");
+
+ memMetrics.subIntervals(subInts);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void enableMetrics() {
+ memMetrics.enableMetrics();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void disableMetrics() {
+ memMetrics.disableMetrics();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getName() {
+ return memMetrics.getName();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getInitialSize() {
+ return (int) (memPlcCfg.getInitialSize() / (1024 * 1024));
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getMaxSize() {
+ return (int) (memPlcCfg.getMaxSize() / (1024 * 1024));
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getSwapFilePath() {
+ return memPlcCfg.getSwapFilePath();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsSnapshot.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsSnapshot.java
new file mode 100644
index 0000000..4e7f90a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryMetricsSnapshot.java
@@ -0,0 +1,112 @@
+/*
+ * 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.MemoryMetrics;
+
+/**
+ *
+ */
+public class MemoryMetricsSnapshot implements MemoryMetrics {
+ /** */
+ private String name;
+
+ /** */
+ private long totalAllocatedPages;
+
+ /** */
+ private float allocationRate;
+
+ /** */
+ private float evictionRate;
+
+ /** */
+ private float largeEntriesPagesPercentage;
+
+ /** */
+ private float pagesFillFactor;
+
+ /** */
+ private long dirtyPages;
+
+ /** */
+ private float pageReplaceRate;
+
+ /** */
+ private long physicalMemoryPages;
+
+ /**
+ * @param metrics Metrics instance to take a copy.
+ */
+ public MemoryMetricsSnapshot(MemoryMetrics metrics) {
+ name = metrics.getName();
+ totalAllocatedPages = metrics.getTotalAllocatedPages();
+ allocationRate = metrics.getAllocationRate();
+ evictionRate = metrics.getEvictionRate();
+ largeEntriesPagesPercentage = metrics.getLargeEntriesPagesPercentage();
+ pagesFillFactor = metrics.getPagesFillFactor();
+ dirtyPages = metrics.getDirtyPages();
+ pageReplaceRate = metrics.getPagesReplaceRate();
+ physicalMemoryPages = metrics.getPhysicalMemoryPages();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getName() {
+ return name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getTotalAllocatedPages() {
+ return totalAllocatedPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getAllocationRate() {
+ return allocationRate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getEvictionRate() {
+ return evictionRate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getLargeEntriesPagesPercentage() {
+ return largeEntriesPagesPercentage;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getPagesFillFactor() {
+ return pagesFillFactor;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDirtyPages() {
+ return dirtyPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getPagesReplaceRate() {
+ return pageReplaceRate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getPhysicalMemoryPages() {
+ return physicalMemoryPages;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicy.java
new file mode 100644
index 0000000..7c7d7bc
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicy.java
@@ -0,0 +1,83 @@
+/*
+ * 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.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.persistence.evict.PageEvictionTracker;
+
+/**
+ * Memory policy provides access to objects configured with {@link MemoryPolicyConfiguration} configuration.
+ */
+public class MemoryPolicy {
+ /** */
+ private final PageMemory pageMem;
+
+ /** */
+ private final MemoryMetricsImpl memMetrics;
+
+ /** */
+ private final MemoryPolicyConfiguration cfg;
+
+ /** */
+ private final PageEvictionTracker evictionTracker;
+
+ /**
+ * @param pageMem PageMemory instance.
+ * @param memMetrics MemoryMetrics instance.
+ * @param cfg Configuration of given MemoryPolicy.
+ * @param evictionTracker Eviction tracker.
+ */
+ public MemoryPolicy(
+ PageMemory pageMem,
+ MemoryPolicyConfiguration cfg,
+ MemoryMetricsImpl memMetrics,
+ PageEvictionTracker evictionTracker) {
+ this.pageMem = pageMem;
+ this.memMetrics = memMetrics;
+ this.cfg = cfg;
+ this.evictionTracker = evictionTracker;
+ }
+
+ /**
+ *
+ */
+ public PageMemory pageMemory() {
+ return pageMem;
+ }
+
+ /**
+ * @return Config.
+ */
+ public MemoryPolicyConfiguration config() {
+ return cfg;
+ }
+
+ /**
+ * @return Memory Metrics.
+ */
+ public MemoryMetricsImpl memoryMetrics() {
+ return memMetrics;
+ }
+
+ /**
+ *
+ */
+ public PageEvictionTracker evictionTracker() {
+ return evictionTracker;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetaStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetaStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetaStore.java
new file mode 100644
index 0000000..c09ce4e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetaStore.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+/**
+ * Meta store.
+ */
+public interface MetaStore {
+ /**
+ * Get or allocate initial page for an index.
+ *
+ * @param idxName Index name.
+ * @return {@link RootPage} that keeps pageId, allocated flag that shows whether the page
+ * 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;
+
+ /**
+ * Deallocate index page and remove from tree.
+ *
+ * @param idxName Index name.
+ * @return Root ID or -1 if no page was removed.
+ * @throws IgniteCheckedException If failed.
+ */
+ public RootPage dropRootPage(String idxName) throws IgniteCheckedException;
+
+ /**
+ * Destroy this meta store.
+ *
+ * @throws IgniteCheckedException If failed.
+ */
+ public void destroy() throws IgniteCheckedException;
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetadataStorage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetadataStorage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetadataStorage.java
new file mode 100644
index 0000000..806afb8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/MetadataStorage.java
@@ -0,0 +1,417 @@
+/*
+ * 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 java.nio.charset.StandardCharsets;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.pagemem.PageUtils;
+import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
+import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusInnerIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusLeafIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersions;
+import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ * Metadata storage.
+ */
+public class MetadataStorage implements MetaStore {
+ /** Max index name length (bytes num) */
+ public static final int MAX_IDX_NAME_LEN = 768;
+
+ /** Bytes in byte. */
+ private static final int BYTE_LEN = 1;
+
+ /** Page memory. */
+ private final PageMemory pageMem;
+
+ /** Index tree. */
+ private final MetaTree metaTree;
+
+ /** Meta page reuse tree. */
+ private final ReuseList reuseList;
+
+ /** Cache group ID. */
+ private final int grpId;
+
+ /** */
+ private final int allocPartId;
+
+ /** */
+ private final byte allocSpace;
+
+ /**
+ * @param pageMem Page memory.
+ * @param wal Write ahead log manager.
+ */
+ public MetadataStorage(
+ final PageMemory pageMem,
+ final IgniteWriteAheadLogManager wal,
+ final AtomicLong globalRmvId,
+ final int grpId,
+ final int allocPartId,
+ final byte allocSpace,
+ final ReuseList reuseList,
+ final long rootPageId,
+ final boolean initNew
+ ) {
+ try {
+ this.pageMem = pageMem;
+ this.grpId = grpId;
+ this.allocPartId = allocPartId;
+ this.allocSpace = allocSpace;
+ this.reuseList = reuseList;
+
+ metaTree = new MetaTree(grpId, allocPartId, allocSpace, pageMem, wal, globalRmvId, rootPageId,
+ reuseList, MetaStoreInnerIO.VERSIONS, MetaStoreLeafIO.VERSIONS, initNew);
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public RootPage getOrAllocateForTree(final String idxName) throws IgniteCheckedException {
+ final MetaTree tree = metaTree;
+
+ synchronized (this) {
+ byte[] idxNameBytes = idxName.getBytes(StandardCharsets.UTF_8);
+
+ if (idxNameBytes.length > MAX_IDX_NAME_LEN)
+ throw new IllegalArgumentException("Too long encoded indexName [maxAllowed=" + MAX_IDX_NAME_LEN +
+ ", currentLength=" + idxNameBytes.length + ", name=" + idxName + "]");
+
+ final IndexItem row = tree.findOne(new IndexItem(idxNameBytes, 0));
+
+ if (row == null) {
+ long pageId = 0;
+
+ if (reuseList != null)
+ pageId = reuseList.takeRecycledPage();
+
+ pageId = pageId == 0 ? pageMem.allocatePage(grpId, allocPartId, allocSpace) : pageId;
+
+ tree.put(new IndexItem(idxNameBytes, pageId));
+
+ return new RootPage(new FullPageId(pageId, grpId), true);
+ }
+ else {
+ final FullPageId pageId = new FullPageId(row.pageId, grpId);
+
+ return new RootPage(pageId, false);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public RootPage dropRootPage(final String idxName)
+ throws IgniteCheckedException {
+ byte[] idxNameBytes = idxName.getBytes(StandardCharsets.UTF_8);
+
+ final IndexItem row = metaTree.remove(new IndexItem(idxNameBytes, 0));
+
+ if (row != null) {
+ if (reuseList == null)
+ pageMem.freePage(grpId, row.pageId);
+ }
+
+ return row != null ? new RootPage(new FullPageId(row.pageId, grpId), false) : null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void destroy() throws IgniteCheckedException {
+ metaTree.destroy();
+ }
+
+ /**
+ *
+ */
+ private static class MetaTree extends BPlusTree<IndexItem, IndexItem> {
+ /** */
+ private final int allocPartId;
+
+ /** */
+ private final byte allocSpace;
+
+ /**
+ * @param pageMem Page memory.
+ * @param metaPageId Meta page ID.
+ * @param reuseList Reuse list.
+ * @param innerIos Inner IOs.
+ * @param leafIos Leaf IOs.
+ * @throws IgniteCheckedException If failed.
+ */
+ private MetaTree(
+ final int cacheId,
+ final int allocPartId,
+ final byte allocSpace,
+ final PageMemory pageMem,
+ final IgniteWriteAheadLogManager wal,
+ final AtomicLong globalRmvId,
+ final long metaPageId,
+ final ReuseList reuseList,
+ final IOVersions<? extends BPlusInnerIO<IndexItem>> innerIos,
+ final IOVersions<? extends BPlusLeafIO<IndexItem>> leafIos,
+ final boolean initNew
+ ) throws IgniteCheckedException {
+ super(treeName("meta", "Meta"), cacheId, pageMem, wal, globalRmvId, metaPageId, reuseList, innerIos, leafIos);
+
+ this.allocPartId = allocPartId;
+ this.allocSpace = allocSpace;
+
+ initTree(initNew);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long allocatePageNoReuse() throws IgniteCheckedException {
+ return pageMem.allocatePage(getCacheId(), allocPartId, allocSpace);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected int compare(final BPlusIO<IndexItem> io, final long pageAddr, final int idx,
+ final IndexItem row) throws IgniteCheckedException {
+ final int off = ((IndexIO)io).getOffset(pageAddr, idx);
+
+ int shift = 0;
+
+ // Compare index names.
+ final byte len = PageUtils.getByte(pageAddr, off + shift);
+
+ shift += BYTE_LEN;
+
+ for (int i = 0; i < len && i < row.idxName.length; i++) {
+ final int cmp = Byte.compare(PageUtils.getByte(pageAddr, off + i + shift), row.idxName[i]);
+
+ if (cmp != 0)
+ return cmp;
+ }
+
+ return Integer.compare(len, row.idxName.length);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IndexItem getRow(final BPlusIO<IndexItem> io, final long pageAddr,
+ final int idx, Object ignore) throws IgniteCheckedException {
+ return readRow(pageAddr, ((IndexIO)io).getOffset(pageAddr, idx));
+ }
+ }
+
+ /**
+ *
+ */
+ private static class IndexItem {
+ /** */
+ private byte[] idxName;
+
+ /** */
+ private long pageId;
+
+ /**
+ * @param idxName Index name.
+ * @param pageId Page ID.
+ */
+ private IndexItem(final byte[] idxName, final long pageId) {
+ this.idxName = idxName;
+ this.pageId = pageId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "I [idxName=" + new String(idxName) + ", pageId=" + U.hexLong(pageId) + ']';
+ }
+ }
+
+ /**
+ * Store row to buffer.
+ *
+ * @param pageAddr Page address.
+ * @param off Offset in buf.
+ * @param row Row to store.
+ */
+ private static void storeRow(
+ final long pageAddr,
+ int off,
+ final IndexItem row
+ ) {
+ // Index name length.
+ PageUtils.putByte(pageAddr, off, (byte)row.idxName.length);
+ off++;
+
+ // Index name.
+ PageUtils.putBytes(pageAddr, off, row.idxName);
+ off += row.idxName.length;
+
+ // Page ID.
+ PageUtils.putLong(pageAddr, off, row.pageId);
+ }
+
+ /**
+ * Copy row data.
+ *
+ * @param dstPageAddr Destination page address.
+ * @param dstOff Destination buf offset.
+ * @param srcPageAddr Source page address.
+ * @param srcOff Src buf offset.
+ */
+ private static void storeRow(
+ final long dstPageAddr,
+ int dstOff,
+ final long srcPageAddr,
+ int srcOff
+ ) {
+ // Index name length.
+ final byte len = PageUtils.getByte(srcPageAddr, srcOff);
+ srcOff++;
+
+ PageUtils.putByte(dstPageAddr, dstOff, len);
+ dstOff++;
+
+ PageHandler.copyMemory(srcPageAddr, dstPageAddr, srcOff, dstOff, len);
+ srcOff += len;
+ dstOff += len;
+
+ // Page ID.
+ PageUtils.putLong(dstPageAddr, dstOff, PageUtils.getLong(srcPageAddr, srcOff));
+ }
+
+ /**
+ * Read row from buffer.
+ *
+ * @param pageAddr Page address.
+ * @param off Offset.
+ * @return Read row.
+ */
+ private static IndexItem readRow(final long pageAddr, int off) {
+ // Index name length.
+ final int len = PageUtils.getByte(pageAddr, off) & 0xFF;
+ off++;
+
+ // Index name.
+ final byte[] idxName = PageUtils.getBytes(pageAddr, off, len);
+ off += len;
+
+ // Page ID.
+ final long pageId = PageUtils.getLong(pageAddr, off);
+
+ return new IndexItem(idxName, pageId);
+ }
+
+ /**
+ *
+ */
+ private interface IndexIO {
+ /**
+ * @param pageAddr Page address.
+ * @param idx Index.
+ * @return Offset in buffer according to {@code idx}.
+ */
+ int getOffset(long pageAddr, int idx);
+ }
+
+ /**
+ *
+ */
+ public static final class MetaStoreInnerIO extends BPlusInnerIO<IndexItem> implements IndexIO {
+ /** */
+ public static final IOVersions<MetaStoreInnerIO> VERSIONS = new IOVersions<>(
+ new MetaStoreInnerIO(1)
+ );
+
+ /**
+ * @param ver Version.
+ */
+ private MetaStoreInnerIO(final int ver) {
+ // name bytes and 1 byte for length, 8 bytes pageId
+ super(T_METASTORE_INNER, ver, false, MAX_IDX_NAME_LEN + 1 + 8);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void storeByOffset(long pageAddr, int off, IndexItem row) throws IgniteCheckedException {
+ storeRow(pageAddr, off, row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void store(final long dstPageAddr, final int dstIdx, final BPlusIO<IndexItem> srcIo,
+ final long srcPageAddr,
+ final int srcIdx) throws IgniteCheckedException {
+ storeRow(dstPageAddr, offset(dstIdx), srcPageAddr, ((IndexIO)srcIo).getOffset(srcPageAddr, srcIdx));
+ }
+
+ /** {@inheritDoc} */
+ @Override public IndexItem getLookupRow(final BPlusTree<IndexItem, ?> tree, final long pageAddr,
+ final int idx) throws IgniteCheckedException {
+ return readRow(pageAddr, offset(idx));
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getOffset(long pageAddr, final int idx) {
+ return offset(idx);
+ }
+ }
+
+ /**
+ *
+ */
+ public static final class MetaStoreLeafIO extends BPlusLeafIO<IndexItem> implements IndexIO {
+ /** */
+ public static final IOVersions<MetaStoreLeafIO> VERSIONS = new IOVersions<>(
+ new MetaStoreLeafIO(1)
+ );
+
+ /**
+ * @param ver Version.
+ */
+ private MetaStoreLeafIO(final int ver) {
+ // 4 byte cache ID, UTF-16 symbols and 1 byte for length, 8 bytes pageId
+ super(T_METASTORE_LEAF, ver, MAX_IDX_NAME_LEN + 1 + 8);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void storeByOffset(long buf, int off, IndexItem row) throws IgniteCheckedException {
+ storeRow(buf, off, row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void store(final long dstPageAddr,
+ final int dstIdx,
+ final BPlusIO<IndexItem> srcIo,
+ final long srcPageAddr,
+ final int srcIdx) throws IgniteCheckedException {
+ storeRow(dstPageAddr, offset(dstIdx), srcPageAddr, ((IndexIO)srcIo).getOffset(srcPageAddr, srcIdx));
+ }
+
+ /** {@inheritDoc} */
+ @Override public IndexItem getLookupRow(final BPlusTree<IndexItem, ?> tree,
+ final long pageAddr,
+ final int idx) throws IgniteCheckedException {
+ return readRow(pageAddr, offset(idx));
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getOffset(long pageAddr, final int idx) {
+ return offset(idx);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsImpl.java
new file mode 100644
index 0000000..7952937
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsImpl.java
@@ -0,0 +1,297 @@
+/*
+ * 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.internal.pagemem.wal.IgniteWriteAheadLogManager;
+import org.apache.ignite.internal.processors.cache.ratemetrics.HitRateMetrics;
+import org.apache.ignite.mxbean.PersistenceMetricsMXBean;
+
+/**
+ *
+ */
+public class PersistenceMetricsImpl implements PersistenceMetricsMXBean {
+ /** */
+ private volatile HitRateMetrics walLoggingRate;
+
+ /** */
+ private volatile HitRateMetrics walWritingRate;
+
+ /** */
+ private volatile HitRateMetrics walFsyncTimeDuration;
+
+ /** */
+ private volatile HitRateMetrics walFsyncTimeNumber;
+
+ /** */
+ private volatile long lastCpLockWaitDuration;
+
+ /** */
+ private volatile long lastCpMarkDuration;
+
+ /** */
+ private volatile long lastCpPagesWriteDuration;
+
+ /** */
+ private volatile long lastCpDuration;
+
+ /** */
+ private volatile long lastCpFsyncDuration;
+
+ /** */
+ private volatile long lastCpTotalPages;
+
+ /** */
+ private volatile long lastCpDataPages;
+
+ /** */
+ private volatile long lastCpCowPages;
+
+ /** */
+ private volatile long rateTimeInterval;
+
+ /** */
+ private volatile int subInts;
+
+ /** */
+ private volatile boolean metricsEnabled;
+
+ /** */
+ private IgniteWriteAheadLogManager wal;
+
+ /**
+ * @param metricsEnabled Metrics enabled flag.
+ * @param rateTimeInterval Rate time interval.
+ * @param subInts Number of sub-intervals.
+ */
+ public PersistenceMetricsImpl(
+ boolean metricsEnabled,
+ long rateTimeInterval,
+ int subInts
+ ) {
+ this.metricsEnabled = metricsEnabled;
+ this.rateTimeInterval = rateTimeInterval;
+ this.subInts = subInts;
+
+ resetRates();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getWalLoggingRate() {
+ if (!metricsEnabled)
+ return 0;
+
+ return ((float)walLoggingRate.getRate()) / rateTimeInterval;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getWalWritingRate() {
+ if (!metricsEnabled)
+ return 0;
+
+ return ((float)walWritingRate.getRate()) / rateTimeInterval;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getWalArchiveSegments() {
+ if (!metricsEnabled)
+ return 0;
+
+ return wal.walArchiveSegments();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getWalFsyncTimeAverage() {
+ if (!metricsEnabled)
+ return 0;
+
+ long numRate = walFsyncTimeNumber.getRate();
+
+ if (numRate == 0)
+ return 0;
+
+ return (float)walFsyncTimeDuration.getRate() / numRate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointingDuration() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointLockWaitDuration() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpLockWaitDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointMarkDuration() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpMarkDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointPagesWriteDuration() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpPagesWriteDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointFsyncDuration() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpFsyncDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointTotalPagesNumber() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpTotalPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointDataPagesNumber() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpDataPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointCopiedOnWritePagesNumber() {
+ if (!metricsEnabled)
+ return 0;
+
+ return lastCpCowPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void enableMetrics() {
+ metricsEnabled = true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void disableMetrics() {
+ metricsEnabled = false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void rateTimeInterval(long rateTimeInterval) {
+ this.rateTimeInterval = rateTimeInterval;
+
+ resetRates();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void subIntervals(int subInts) {
+ this.subInts = subInts;
+
+ resetRates();
+ }
+
+ /**
+ * @param wal Write-ahead log manager.
+ */
+ public void wal(IgniteWriteAheadLogManager wal) {
+ this.wal = wal;
+ }
+
+ /**
+ * @return Metrics enabled flag.
+ */
+ public boolean metricsEnabled() {
+ return metricsEnabled;
+ }
+
+ /**
+ * @param lockWaitDuration Lock wait duration.
+ * @param markDuration Mark duration.
+ * @param pagesWriteDuration Pages write duration.
+ * @param fsyncDuration Total checkpoint fsync duration.
+ * @param duration Total checkpoint duration.
+ * @param totalPages Total number of all pages in checkpoint.
+ * @param dataPages Total number of data pages in checkpoint.
+ * @param cowPages Total number of COW-ed pages in checkpoint.
+ */
+ public void onCheckpoint(
+ long lockWaitDuration,
+ long markDuration,
+ long pagesWriteDuration,
+ long fsyncDuration,
+ long duration,
+ long totalPages,
+ long dataPages,
+ long cowPages
+ ) {
+ if (metricsEnabled) {
+ lastCpLockWaitDuration = lockWaitDuration;
+ lastCpMarkDuration = markDuration;
+ lastCpPagesWriteDuration = pagesWriteDuration;
+ lastCpFsyncDuration = fsyncDuration;
+ lastCpDuration = duration;
+ lastCpTotalPages = totalPages;
+ lastCpDataPages = dataPages;
+ lastCpCowPages = cowPages;
+ }
+ }
+
+ /**
+ *
+ */
+ public void onWalRecordLogged() {
+ walLoggingRate.onHit();
+ }
+
+ /**
+ * @param size Size written.
+ */
+ public void onWalBytesWritten(int size) {
+ walWritingRate.onHits(size);
+ }
+
+ /**
+ * @param nanoTime Fsync nano time.
+ */
+ public void onFsync(long nanoTime) {
+ long microseconds = nanoTime / 1_000;
+
+ walFsyncTimeDuration.onHits(microseconds);
+ walFsyncTimeNumber.onHit();
+ }
+
+ /**
+ *
+ */
+ private void resetRates() {
+ walLoggingRate = new HitRateMetrics((int)rateTimeInterval, subInts);
+ walWritingRate = new HitRateMetrics((int)rateTimeInterval, subInts);
+
+ walFsyncTimeDuration = new HitRateMetrics((int)rateTimeInterval, subInts);
+ walFsyncTimeNumber = new HitRateMetrics((int)rateTimeInterval, subInts);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsSnapshot.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsSnapshot.java
new file mode 100644
index 0000000..0de9950
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/PersistenceMetricsSnapshot.java
@@ -0,0 +1,144 @@
+/*
+ * 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.PersistenceMetrics;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ *
+ */
+public class PersistenceMetricsSnapshot implements PersistenceMetrics {
+ /** */
+ private float walLoggingRate;
+
+ /** */
+ private float walWritingRate;
+
+ /** */
+ private int walArchiveSegments;
+
+ /** */
+ private float walFsyncTimeAvg;
+
+ /** */
+ private long lastCpDuration;
+
+ /** */
+ private long lastCpLockWaitDuration;
+
+ /** */
+ private long lastCpMmarkDuration;
+
+ /** */
+ private long lastCpPagesWriteDuration;
+
+ /** */
+ private long lastCpFsyncDuration;
+
+ /** */
+ private long lastCpTotalPages;
+
+ /** */
+ private long lastCpDataPages;
+
+ /** */
+ private long lastCpCowPages;
+
+ /**
+ * @param metrics Metrics.
+ */
+ public PersistenceMetricsSnapshot(PersistenceMetrics metrics) {
+ walLoggingRate = metrics.getWalLoggingRate();
+ walWritingRate = metrics.getWalWritingRate();
+ walArchiveSegments = metrics.getWalArchiveSegments();
+ walFsyncTimeAvg = metrics.getWalFsyncTimeAverage();
+ lastCpDuration = metrics.getLastCheckpointingDuration();
+ lastCpLockWaitDuration = metrics.getLastCheckpointLockWaitDuration();
+ lastCpMmarkDuration = metrics.getLastCheckpointMarkDuration();
+ lastCpPagesWriteDuration = metrics.getLastCheckpointPagesWriteDuration();
+ lastCpFsyncDuration = metrics.getLastCheckpointFsyncDuration();
+ lastCpTotalPages = metrics.getLastCheckpointTotalPagesNumber();
+ lastCpDataPages = metrics.getLastCheckpointDataPagesNumber();
+ lastCpCowPages = metrics.getLastCheckpointCopiedOnWritePagesNumber();
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getWalLoggingRate() {
+ return walLoggingRate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getWalWritingRate() {
+ return walWritingRate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getWalArchiveSegments() {
+ return walArchiveSegments;
+ }
+
+ /** {@inheritDoc} */
+ @Override public float getWalFsyncTimeAverage() {
+ return walFsyncTimeAvg;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointingDuration() {
+ return lastCpDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointLockWaitDuration() {
+ return lastCpLockWaitDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointMarkDuration() {
+ return lastCpMmarkDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointPagesWriteDuration() {
+ return lastCpPagesWriteDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointFsyncDuration() {
+ return lastCpFsyncDuration;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointTotalPagesNumber() {
+ return lastCpTotalPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointDataPagesNumber() {
+ return lastCpDataPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getLastCheckpointCopiedOnWritePagesNumber() {
+ return lastCpCowPages;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(PersistenceMetricsSnapshot.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RootPage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RootPage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RootPage.java
new file mode 100644
index 0000000..da9efe5
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RootPage.java
@@ -0,0 +1,62 @@
+/*
+ * 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.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ *
+ */
+public class RootPage {
+ /** */
+ @GridToStringInclude
+ private FullPageId pageId;
+
+ /** */
+ private boolean allocated;
+
+ /**
+ * @param pageId Page ID.
+ * @param allocated {@code True} if was allocated new page.
+ */
+ public RootPage(final FullPageId pageId, final boolean allocated) {
+ this.pageId = pageId;
+ this.allocated = allocated;
+ }
+
+ /**
+ * @return Page ID.
+ */
+ public FullPageId pageId() {
+ return pageId;
+ }
+
+ /**
+ * @return {@code True} if was allocated.
+ */
+ public boolean isAllocated() {
+ return allocated;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(RootPage.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RowStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RowStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RowStore.java
new file mode 100644
index 0000000..9cc5c62
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/RowStore.java
@@ -0,0 +1,107 @@
+/*
+ * 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.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.CacheGroupContext;
+import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList;
+
+/**
+ * Data store for H2 rows.
+ */
+public class RowStore {
+ /** */
+ private final FreeList freeList;
+
+ /** */
+ private final GridCacheSharedContext ctx;
+
+ /** */
+ protected final PageMemory pageMem;
+
+ /** */
+ protected final CacheObjectContext coctx;
+
+
+
+ /**
+ * @param grp Cache group.
+ * @param freeList Free list.
+ */
+ public RowStore(CacheGroupContext grp, FreeList freeList) {
+ assert grp != null;
+ assert freeList != null;
+
+ this.freeList = freeList;
+
+ ctx = grp.shared();
+ coctx = grp.cacheObjectContext();
+ pageMem = grp.memoryPolicy().pageMemory();
+ }
+
+ /**
+ * @param link Row link.
+ * @throws IgniteCheckedException If failed.
+ */
+ public void removeRow(long link) throws IgniteCheckedException {
+ assert link != 0;
+ ctx.database().checkpointReadLock();
+
+ try {
+ freeList.removeDataRowByLink(link);
+ }
+ finally {
+ ctx.database().checkpointReadUnlock();
+ }
+ }
+
+ /**
+ * @param row Row.
+ * @throws IgniteCheckedException If failed.
+ */
+ public void addRow(CacheDataRow row) throws IgniteCheckedException {
+ ctx.database().checkpointReadLock();
+
+ try {
+ freeList.insertDataRow(row);
+ }
+ finally {
+ ctx.database().checkpointReadUnlock();
+ }
+ }
+
+ /**
+ * @param link Row link.
+ * @param row New row data.
+ * @throws IgniteCheckedException If failed.
+ * @return {@code True} if was able to update row.
+ */
+ public boolean updateRow(long link, CacheDataRow row) throws IgniteCheckedException {
+ return freeList.updateDataRow(link, row);
+ }
+
+ /**
+ * @return Free list.
+ */
+ public FreeList freeList() {
+ return freeList;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/FairFifoPageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/FairFifoPageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/FairFifoPageEvictionTracker.java
new file mode 100644
index 0000000..f5c7c8a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/FairFifoPageEvictionTracker.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.cache.persistence.evict;
+
+import java.util.LinkedList;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+
+/**
+ * On-heap FIFO page eviction tracker. Only for test purposes.
+ */
+public class FairFifoPageEvictionTracker extends PageAbstractEvictionTracker {
+ /** Page usage deque. */
+ private final LinkedList<Integer> pageUsageList = new LinkedList<>();
+
+ /**
+ * @param pageMem Page memory.
+ * @param plcCfg Memory policy configuration.
+ * @param sharedCtx Shared context.
+ */
+ public FairFifoPageEvictionTracker(
+ PageMemoryNoStoreImpl pageMem,
+ MemoryPolicyConfiguration plcCfg,
+ GridCacheSharedContext sharedCtx) {
+ super(pageMem, plcCfg, sharedCtx);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void touchPage(long pageId) throws IgniteCheckedException {
+ pageUsageList.addLast(PageIdUtils.pageIndex(pageId));
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void evictDataPage() throws IgniteCheckedException {
+ evictDataPage(pageUsageList.pollFirst());
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void forgetPage(long pageId) throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected synchronized boolean checkTouch(long pageId) {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/NoOpPageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/NoOpPageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/NoOpPageEvictionTracker.java
new file mode 100644
index 0000000..b420ecd
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/NoOpPageEvictionTracker.java
@@ -0,0 +1,50 @@
+/*
+* 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.evict;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+
+/**
+ *
+ */
+public class NoOpPageEvictionTracker implements PageEvictionTracker {
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void touchPage(long pageId) throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void evictDataPage() throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void forgetPage(long pageId) throws IgniteCheckedException {
+ // No-op.
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageAbstractEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageAbstractEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageAbstractEvictionTracker.java
new file mode 100644
index 0000000..a524d5e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageAbstractEvictionTracker.java
@@ -0,0 +1,171 @@
+/*
+* 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.evict;
+
+import java.util.List;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersionManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ *
+ */
+public abstract class PageAbstractEvictionTracker implements PageEvictionTracker {
+ /** This number of least significant bits is dropped from timestamp. */
+ private static final int COMPACT_TS_SHIFT = 8; // Enough if grid works for less than 17 years.
+
+ /** Millis in day. */
+ private static final int DAY = 24 * 60 * 60 * 1000;
+
+ /** Page memory. */
+ protected final PageMemoryNoStoreImpl pageMem;
+
+ /** Tracking array size. */
+ protected final int trackingSize;
+
+ /** Base compact timestamp. */
+ private final long baseCompactTs;
+
+ /** Shared context. */
+ private final GridCacheSharedContext sharedCtx;
+
+ /**
+ * @param pageMem Page memory.
+ * @param plcCfg Memory policy configuration.
+ * @param sharedCtx Shared context.
+ */
+ PageAbstractEvictionTracker(
+ PageMemoryNoStoreImpl pageMem,
+ MemoryPolicyConfiguration plcCfg,
+ GridCacheSharedContext sharedCtx
+ ) {
+ this.pageMem = pageMem;
+
+ this.sharedCtx = sharedCtx;
+
+ trackingSize = pageMem.totalPages();
+
+ baseCompactTs = (U.currentTimeMillis() - DAY) >> COMPACT_TS_SHIFT;
+ // We subtract day to avoid fail in case of daylight shift or timezone change.
+ }
+
+ /**
+ * @param pageIdx Page index.
+ * @return true if at least one data row has been evicted
+ * @throws IgniteCheckedException If failed.
+ */
+ final boolean evictDataPage(int pageIdx) throws IgniteCheckedException {
+ long fakePageId = PageIdUtils.pageId(0, (byte)0, pageIdx);
+
+ long page = pageMem.acquirePage(0, fakePageId);
+
+ List<CacheDataRowAdapter> rowsToEvict;
+
+ try {
+ long pageAddr = pageMem.readLockForce(0, fakePageId, page);
+
+ try {
+ if (PageIO.getType(pageAddr) != PageIO.T_DATA)
+ return false; // Can't evict: page has been recycled into non-data page.
+
+ DataPageIO io = DataPageIO.VERSIONS.forPage(pageAddr);
+
+ long realPageId = PageIO.getPageId(pageAddr);
+
+ if (!checkTouch(realPageId))
+ return false; // Can't evict: another thread concurrently invoked forgetPage()
+
+ rowsToEvict = io.forAllItems(pageAddr, new DataPageIO.CC<CacheDataRowAdapter>() {
+ @Override public CacheDataRowAdapter apply(long link) throws IgniteCheckedException {
+ CacheDataRowAdapter row = new CacheDataRowAdapter(link);
+
+ row.initFromLink(null, sharedCtx, pageMem, CacheDataRowAdapter.RowData.KEY_ONLY);
+
+ assert row.cacheId() != 0 : "Cache ID should be stored in rows of evictable cache";
+
+ return row;
+ }
+ });
+ }
+ finally {
+ pageMem.readUnlock(0, fakePageId, page);
+ }
+ }
+ finally {
+ pageMem.releasePage(0, fakePageId, page);
+ }
+
+ boolean evictionDone = false;
+
+ for (CacheDataRowAdapter dataRow : rowsToEvict) {
+ GridCacheContext<?, ?> cacheCtx = sharedCtx.cacheContext(dataRow.cacheId());
+
+ if (!cacheCtx.userCache())
+ continue;
+
+ GridCacheEntryEx entryEx = cacheCtx.isNear() ? cacheCtx.near().dht().entryEx(dataRow.key()) :
+ cacheCtx.cache().entryEx(dataRow.key());
+
+ evictionDone |= entryEx.evictInternal(GridCacheVersionManager.EVICT_VER, null, true);
+ }
+
+ return evictionDone;
+ }
+
+ /**
+ * @param pageId Page ID.
+ * @return true if page was touched at least once.
+ */
+ protected abstract boolean checkTouch(long pageId);
+
+ /**
+ * @param epochMilli Time millis.
+ * @return Compact timestamp. Comparable and fits in 4 bytes.
+ */
+ final long compactTimestamp(long epochMilli) {
+ return (epochMilli >> COMPACT_TS_SHIFT) - baseCompactTs;
+ }
+
+ /**
+ * Resolves position in tracking array by page index.
+ *
+ * @param pageIdx Page index.
+ * @return Position of page in tracking array.
+ */
+ int trackingIdx(int pageIdx) {
+ return pageMem.pageSequenceNumber(pageIdx);
+ }
+
+ /**
+ * Reverse of {@link #trackingIdx(int)}.
+ *
+ * @param trackingIdx Tracking index.
+ * @return Page index.
+ */
+ int pageIdx(int trackingIdx) {
+ return pageMem.pageIndex(trackingIdx);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageEvictionTracker.java
new file mode 100644
index 0000000..baa5462
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/PageEvictionTracker.java
@@ -0,0 +1,52 @@
+/*
+* 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.evict;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.lifecycle.LifecycleAware;
+
+/**
+ * Entry point for per-page eviction. Accepts information about touching data pages,
+ * capable of evicting "the least needed" page (according to implemented eviction algorithm).
+ */
+public interface PageEvictionTracker extends LifecycleAware {
+ /**
+ * Call this method when data page is accessed.
+ *
+ * @param pageId Page id.
+ * @throws IgniteCheckedException In case of page memory error.
+ */
+ public void touchPage(long pageId) throws IgniteCheckedException;
+
+ /**
+ * Evicts one data page.
+ * In most cases, all entries will be removed from the page.
+ * Method guarantees removing at least one entry from "evicted" data page. Removing all entries may be
+ * not possible, as some of them can be used by active transactions.
+ *
+ * @throws IgniteCheckedException In case of page memory error.
+ */
+ public void evictDataPage() throws IgniteCheckedException;
+
+ /**
+ * Call this method when last entry is removed from data page.
+ *
+ * @param pageId Page id.
+ * @throws IgniteCheckedException In case of page memory error.
+ */
+ public void forgetPage(long pageId) throws IgniteCheckedException;
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6bf5ce46/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/Random2LruPageEvictionTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/Random2LruPageEvictionTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/Random2LruPageEvictionTracker.java
new file mode 100644
index 0000000..00f1b16
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/evict/Random2LruPageEvictionTracker.java
@@ -0,0 +1,180 @@
+/*
+* 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.evict;
+
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.internal.util.typedef.internal.LT;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ *
+ */
+public class Random2LruPageEvictionTracker extends PageAbstractEvictionTracker {
+ /** Evict attempts limit. */
+ private static final int EVICT_ATTEMPTS_LIMIT = 30;
+
+ /** LRU Sample size. */
+ private static final int SAMPLE_SIZE = 5;
+
+ /** Maximum sample search spin count */
+ private static final int SAMPLE_SPIN_LIMIT = SAMPLE_SIZE * 1000;
+
+ /** Logger. */
+ private final IgniteLogger log;
+
+ /** Tracking array ptr. */
+ private long trackingArrPtr;
+
+ /**
+ * @param pageMem Page memory.
+ * @param plcCfg Policy config.
+ * @param sharedCtx Shared context.
+ */
+ public Random2LruPageEvictionTracker(
+ PageMemoryNoStoreImpl pageMem,
+ MemoryPolicyConfiguration plcCfg,
+ GridCacheSharedContext<?, ?> sharedCtx
+ ) {
+ super(pageMem, plcCfg, sharedCtx);
+
+ MemoryConfiguration memCfg = sharedCtx.kernalContext().config().getMemoryConfiguration();
+
+ assert plcCfg.getMaxSize() / memCfg.getPageSize() < Integer.MAX_VALUE;
+
+ log = sharedCtx.logger(getClass());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ trackingArrPtr = GridUnsafe.allocateMemory(trackingSize * 8);
+
+ GridUnsafe.setMemory(trackingArrPtr, trackingSize * 8, (byte)0);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ GridUnsafe.freeMemory(trackingArrPtr);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void touchPage(long pageId) throws IgniteCheckedException {
+ int pageIdx = PageIdUtils.pageIndex(pageId);
+
+ long latestTs = compactTimestamp(U.currentTimeMillis());
+
+ assert latestTs >= 0 && latestTs < Integer.MAX_VALUE;
+
+ boolean success;
+
+ do {
+ int trackingIdx = trackingIdx(pageIdx);
+
+ int firstTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8);
+
+ int secondTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8 + 4);
+
+ if (firstTs <= secondTs)
+ success = GridUnsafe.compareAndSwapInt(null, trackingArrPtr + trackingIdx * 8, firstTs, (int)latestTs);
+ else {
+ success = GridUnsafe.compareAndSwapInt(
+ null, trackingArrPtr + trackingIdx * 8 + 4, secondTs, (int)latestTs);
+ }
+ } while (!success);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void evictDataPage() throws IgniteCheckedException {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ int evictAttemptsCnt = 0;
+
+ while (evictAttemptsCnt < EVICT_ATTEMPTS_LIMIT) {
+ int lruTrackingIdx = -1;
+
+ int lruCompactTs = Integer.MAX_VALUE;
+
+ int dataPagesCnt = 0;
+
+ int sampleSpinCnt = 0;
+
+ while (dataPagesCnt < SAMPLE_SIZE) {
+ int trackingIdx = rnd.nextInt(trackingSize);
+
+ int firstTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8);
+
+ int secondTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8 + 4);
+
+ int minTs = Math.min(firstTs, secondTs);
+
+ int maxTs = Math.max(firstTs, secondTs);
+
+ if (maxTs != 0) {
+ // We chose data page with at least one touch.
+ if (minTs < lruCompactTs) {
+ lruTrackingIdx = trackingIdx;
+
+ lruCompactTs = minTs;
+ }
+
+ dataPagesCnt++;
+ }
+
+ sampleSpinCnt++;
+
+ if (sampleSpinCnt > SAMPLE_SPIN_LIMIT) {
+ LT.warn(log, "Too many attempts to choose data page: " + SAMPLE_SPIN_LIMIT);
+
+ return;
+ }
+ }
+
+ if (evictDataPage(pageIdx(lruTrackingIdx)))
+ return;
+
+ evictAttemptsCnt++;
+ }
+
+ LT.warn(log, "Too many failed attempts to evict page: " + EVICT_ATTEMPTS_LIMIT);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean checkTouch(long pageId) {
+ int trackingIdx = trackingIdx(PageIdUtils.pageIndex(pageId));
+
+ int firstTs = GridUnsafe.getIntVolatile(null, trackingArrPtr + trackingIdx * 8);
+
+ return firstTs != 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void forgetPage(long pageId) {
+ int pageIdx = PageIdUtils.pageIndex(pageId);
+
+ int trackingIdx = trackingIdx(pageIdx);
+
+ GridUnsafe.putLongVolatile(null, trackingArrPtr + trackingIdx * 8, 0L);
+ }
+}