You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2019/12/24 07:44:15 UTC
[ignite] branch master updated: IGNITE-12301 Free-lists system view
- Fixes #6991.
This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 77d21ea IGNITE-12301 Free-lists system view - Fixes #6991.
77d21ea is described below
commit 77d21eaa367ea293233078e85ed0c967dc2b6ee7
Author: Aleksey Plekhanov <pl...@gmail.com>
AuthorDate: Tue Dec 24 10:32:35 2019 +0300
IGNITE-12301 Free-lists system view - Fixes #6991.
Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
.../internal/jdbc2/JdbcMetadataSelfTest.java | 3 +-
.../ignite/jdbc/thin/JdbcThinMetadataSelfTest.java | 18 +++-
.../SystemViewRowAttributeWalkerGenerator.java | 38 +++++++
...dapter.java => FiltrableSystemViewAdapter.java} | 57 +++++-----
.../managers/systemview/GridSystemViewManager.java | 27 ++++-
.../SystemViewInnerCollectionsAdapter.java | 6 +-
.../walker/CachePagesListViewWalker.java | 78 ++++++++++++++
.../managers/systemview/walker/Filtrable.java | 35 ++++++
.../systemview/walker/PagesListViewWalker.java | 68 ++++++++++++
.../processors/cache/GridCacheProcessor.java | 77 ++++++++++++--
.../IgniteCacheDatabaseSharedManager.java | 29 ++++-
.../cache/persistence/freelist/PagesList.java | 45 ++++++++
.../spi/metric/jmx/ReadOnlyDynamicMBean.java | 2 +
.../ignite/spi/systemview/jmx/SystemViewMBean.java | 118 +++++++++++++++++----
.../spi/systemview/view/CachePagesListView.java | 58 ++++++++++
.../spi/systemview/view/FiltrableSystemView.java | 34 ++++++
.../ignite/spi/systemview/view/PagesListView.java | 83 +++++++++++++++
.../view/SystemViewRowAttributeWalker.java | 10 ++
.../ignite/internal/metric/JmxExporterSpiTest.java | 62 +++++++++++
.../ignite/internal/metric/SystemViewSelfTest.java | 100 +++++++++++++++++
.../processors/query/h2/sys/SqlSystemIndex.java | 18 +++-
.../query/h2/sys/SystemViewH2Adapter.java | 18 ++--
.../h2/sys/view/SqlAbstractLocalSystemView.java | 1 -
.../query/h2/sys/view/SqlAbstractSystemView.java | 5 +
.../query/h2/sys/view/SqlSystemView.java | 5 +
.../spi/systemview/FiltrableSystemViewLocal.java | 98 +++++++++++++++++
.../ignite/spi/systemview/SqlViewExporterSpi.java | 4 +-
.../ignite/spi/systemview/SystemViewLocal.java | 37 +++++--
.../cache/metric/SqlViewExporterSpiTest.java | 86 ++++++++++++++-
29 files changed, 1124 insertions(+), 96 deletions(-)
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
index 61d9a27..8c0758a 100755
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
@@ -341,7 +341,8 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
"VIEW_COLUMNS",
"CONTINUOUS_QUERIES",
"STRIPED_THREADPOOL_QUEUE",
- "DATASTREAM_THREADPOOL_QUEUE"
+ "DATASTREAM_THREADPOOL_QUEUE",
+ "CACHE_GROUP_PAGE_LISTS"
));
Set<String> actViews = new HashSet<>();
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
index 9655f9a..aad627a 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
@@ -355,7 +355,9 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
"SYS.VIEW_COLUMNS",
"SYS.CONTINUOUS_QUERIES",
"SYS.STRIPED_THREADPOOL_QUEUE",
- "SYS.DATASTREAM_THREADPOOL_QUEUE"
+ "SYS.DATASTREAM_THREADPOOL_QUEUE",
+ "SYS.CACHE_GROUP_PAGE_LISTS",
+ "SYS.DATA_REGION_PAGE_LISTS"
))
);
}
@@ -866,7 +868,19 @@ public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
"SYS.DATASTREAM_THREADPOOL_QUEUE.STRIPE_INDEX.null.10",
"SYS.DATASTREAM_THREADPOOL_QUEUE.DESCRIPTION.null.2147483647",
"SYS.DATASTREAM_THREADPOOL_QUEUE.THREAD_NAME.null.2147483647",
- "SYS.DATASTREAM_THREADPOOL_QUEUE.TASK_NAME.null.2147483647"
+ "SYS.DATASTREAM_THREADPOOL_QUEUE.TASK_NAME.null.2147483647",
+ "SYS.CACHE_GROUP_PAGE_LISTS.CACHE_GROUP_ID.null.10",
+ "SYS.CACHE_GROUP_PAGE_LISTS.PARTITION_ID.null.10",
+ "SYS.CACHE_GROUP_PAGE_LISTS.NAME.null.2147483647",
+ "SYS.CACHE_GROUP_PAGE_LISTS.BUCKET_NUMBER.null.10",
+ "SYS.CACHE_GROUP_PAGE_LISTS.BUCKET_SIZE.null.19",
+ "SYS.CACHE_GROUP_PAGE_LISTS.STRIPES_COUNT.null.10",
+ "SYS.CACHE_GROUP_PAGE_LISTS.CACHED_PAGES_COUNT.null.10",
+ "SYS.DATA_REGION_PAGE_LISTS.NAME.null.2147483647",
+ "SYS.DATA_REGION_PAGE_LISTS.BUCKET_NUMBER.null.10",
+ "SYS.DATA_REGION_PAGE_LISTS.BUCKET_SIZE.null.19",
+ "SYS.DATA_REGION_PAGE_LISTS.STRIPES_COUNT.null.10",
+ "SYS.DATA_REGION_PAGE_LISTS.CACHED_PAGES_COUNT.null.10"
));
Assert.assertEquals(expectedCols, actualSystemCols);
diff --git a/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java b/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java
index 1fa96c6..300084b 100644
--- a/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java
+++ b/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java
@@ -32,8 +32,12 @@ import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.ObjIntConsumer;
+import org.apache.ignite.internal.managers.systemview.walker.Filtrable;
import org.apache.ignite.internal.managers.systemview.walker.Order;
+import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.spi.systemview.SystemViewLocal;
+import org.apache.ignite.spi.systemview.view.CachePagesListView;
+import org.apache.ignite.spi.systemview.view.PagesListView;
import org.apache.ignite.spi.systemview.jmx.SystemViewMBean;
import org.apache.ignite.spi.systemview.view.CacheGroupView;
import org.apache.ignite.spi.systemview.view.CacheView;
@@ -96,6 +100,8 @@ public class SystemViewRowAttributeWalkerGenerator {
gen.generateAndWrite(SqlQueryView.class, DFLT_SRC_DIR);
gen.generateAndWrite(SqlQueryHistoryView.class, DFLT_SRC_DIR);
gen.generateAndWrite(StripedExecutorTaskView.class, DFLT_SRC_DIR);
+ gen.generateAndWrite(PagesListView.class, DFLT_SRC_DIR);
+ gen.generateAndWrite(CachePagesListView.class, DFLT_SRC_DIR);
gen.generateAndWrite(SqlSchemaView.class, INDEXING_SRC_DIR);
gen.generateAndWrite(SqlTableView.class, INDEXING_SRC_DIR);
@@ -155,6 +161,38 @@ public class SystemViewRowAttributeWalkerGenerator {
code.add(" * @see " + simpleName);
code.add(" */");
code.add("public class " + simpleName + "Walker implements SystemViewRowAttributeWalker<" + simpleName + "> {");
+
+ List<String> filtrableAttrs = new ArrayList<>();
+
+ forEachMethod(clazz, (m, i) -> {
+ if (m.getAnnotation(Filtrable.class) != null) {
+ code.add(TAB + "/** Filter key for attribute \"" + m.getName() + "\" */");
+ code.add(TAB + "public static final String " + m.getName()
+ .replaceAll("(\\p{Upper})", "_$1")
+ .toUpperCase() + "_FILTER = \"" + m.getName() + "\";");
+ code.add("");
+
+ filtrableAttrs.add(m.getName());
+ }
+ });
+
+ if (!filtrableAttrs.isEmpty()) {
+ addImport(imports, F.class);
+ addImport(imports, List.class);
+ addImport(imports, Collections.class);
+
+ code.add(TAB + "/** List of filtrable attributes. */");
+ code.add(TAB + "private static final List<String> FILTRABLE_ATTRS = Collections.unmodifiableList(F.asList(");
+ code.add(TAB + TAB + '\"' + String.join("\", \"", filtrableAttrs) + '\"');
+ code.add(TAB + "));");
+ code.add("");
+ code.add(TAB + "/** {@inheritDoc} */");
+ code.add(TAB + "@Override public List<String> filtrableAttributes() {");
+ code.add(TAB + TAB + "return FILTRABLE_ATTRS;");
+ code.add(TAB + "}");
+ code.add("");
+ }
+
code.add(TAB + "/** {@inheritDoc} */");
code.add(TAB + "@Override public void visitAll(AttributeVisitor v) {");
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/SystemViewInnerCollectionsAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/FiltrableSystemViewAdapter.java
similarity index 52%
copy from modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/SystemViewInnerCollectionsAdapter.java
copy to modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/FiltrableSystemViewAdapter.java
index 1839302..38e5072 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/SystemViewInnerCollectionsAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/FiltrableSystemViewAdapter.java
@@ -17,65 +17,58 @@
package org.apache.ignite.internal.managers.systemview;
-import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
-import java.util.function.BiFunction;
+import java.util.Map;
import java.util.function.Function;
import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.spi.systemview.view.SystemView;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.spi.systemview.view.FiltrableSystemView;
import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker;
import org.jetbrains.annotations.NotNull;
/**
- * System view backed by {@code data} container.
- * Each instance of {@code containers} collections should provide a collection of data.
- *
- * @see SystemView
+ * System view which supports attribute filtering.
*/
-public class SystemViewInnerCollectionsAdapter<C, R, D> extends AbstractSystemView<R> {
- /** Collections of the data containers. */
- private final Collection<C> containers;
-
- /** Function to extract collection of the data from container. */
- private final Function<C, Collection<D>> dataExtractor;
+public class FiltrableSystemViewAdapter<R, D> extends AbstractSystemView<R> implements FiltrableSystemView<R> {
+ /** Data supplier for the view. */
+ private Function<Map<String, Object>, Iterable<D>> dataSupplier;
/** Row function. */
- private final BiFunction<C, D, R> rowFunc;
+ private final Function<D, R> rowFunc;
/**
* @param name Name.
* @param desc Description.
* @param walker Walker.
- * @param containers Container of data.
- * @param dataExtractor Data extractor function.
+ * @param dataSupplier Data supplier.
* @param rowFunc Row function.
*/
- public SystemViewInnerCollectionsAdapter(String name, String desc,
- SystemViewRowAttributeWalker<R> walker,
- Collection<C> containers,
- Function<C, Collection<D>> dataExtractor,
- BiFunction<C, D, R> rowFunc) {
+ public FiltrableSystemViewAdapter(String name, String desc, SystemViewRowAttributeWalker<R> walker,
+ Function<Map<String, Object>, Iterable<D>> dataSupplier, Function<D, R> rowFunc) {
super(name, desc, walker);
- this.containers = containers;
- this.dataExtractor = dataExtractor;
+ A.notNull(dataSupplier, "dataSupplier");
+
+ this.dataSupplier = dataSupplier;
this.rowFunc = rowFunc;
}
/** {@inheritDoc} */
- @Override public int size() {
- int sz = 0;
-
- for (C c : containers)
- sz += dataExtractor.apply(c).size();
+ @NotNull @Override public Iterator<R> iterator(Map<String, Object> filter) {
+ if (filter == null)
+ filter = Collections.emptyMap();
- return sz;
+ return F.iterator(dataSupplier.apply(filter), rowFunc::apply, true);
}
/** {@inheritDoc} */
@NotNull @Override public Iterator<R> iterator() {
- return F.concat(F.iterator(containers,
- c -> F.iterator(dataExtractor.apply(c).iterator(),
- d -> rowFunc.apply(c, d), true), true));
+ return iterator(Collections.emptyMap());
+ }
+
+ /** {@inheritDoc} */
+ @Override public int size() {
+ return F.size(dataSupplier.apply(Collections.emptyMap()).iterator());
}
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/GridSystemViewManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/GridSystemViewManager.java
index e244da6..f16f56b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/GridSystemViewManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/GridSystemViewManager.java
@@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.BiFunction;
@@ -154,7 +155,7 @@ public class GridSystemViewManager extends GridManagerAdapter<SystemViewExporter
* @param <D> Collection data type.
*/
public <C, R, D> void registerInnerCollectionView(String name, String desc, SystemViewRowAttributeWalker<R> walker,
- Collection<C> container, Function<C, Collection<D>> dataExtractor, BiFunction<C, D, R> rowFunc) {
+ Iterable<C> container, Function<C, Collection<D>> dataExtractor, BiFunction<C, D, R> rowFunc) {
registerView0(name, new SystemViewInnerCollectionsAdapter<>(name,
desc,
walker,
@@ -207,15 +208,33 @@ public class GridSystemViewManager extends GridManagerAdapter<SystemViewExporter
}
/**
+ * Registers {@link FiltrableSystemViewAdapter} view with content filtering capabilities.
+ *
+ * @param name Name.
+ * @param desc Description.
+ * @param walker Row walker.
+ * @param dataSupplier Data supplier with content filtering capabilities.
+ * @param rowFunc Row function
+ * @param <R> View row type.
+ * @param <D> Collection data type.
+ */
+ public <R, D> void registerFiltrableView(String name, String desc, SystemViewRowAttributeWalker<R> walker,
+ Function<Map<String, Object>, Iterable<D>> dataSupplier, Function<D, R> rowFunc) {
+ registerView0(name, new FiltrableSystemViewAdapter<>(name,
+ desc,
+ walker,
+ dataSupplier,
+ rowFunc));
+ }
+
+ /**
* Registers view.
*
* @param name Name.
* @param sysView System view.
*/
private void registerView0(String name, SystemView sysView) {
- SystemView<?> old = systemViews.putIfAbsent(name, sysView);
-
- assert old == null;
+ systemViews.put(name, sysView);
notifyListeners(sysView, viewCreationLsnrs, log);
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/SystemViewInnerCollectionsAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/SystemViewInnerCollectionsAdapter.java
index 1839302..326a1d0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/SystemViewInnerCollectionsAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/SystemViewInnerCollectionsAdapter.java
@@ -33,8 +33,8 @@ import org.jetbrains.annotations.NotNull;
* @see SystemView
*/
public class SystemViewInnerCollectionsAdapter<C, R, D> extends AbstractSystemView<R> {
- /** Collections of the data containers. */
- private final Collection<C> containers;
+ /** Iterable of the data containers. */
+ private final Iterable<C> containers;
/** Function to extract collection of the data from container. */
private final Function<C, Collection<D>> dataExtractor;
@@ -52,7 +52,7 @@ public class SystemViewInnerCollectionsAdapter<C, R, D> extends AbstractSystemVi
*/
public SystemViewInnerCollectionsAdapter(String name, String desc,
SystemViewRowAttributeWalker<R> walker,
- Collection<C> containers,
+ Iterable<C> containers,
Function<C, Collection<D>> dataExtractor,
BiFunction<C, D, R> rowFunc) {
super(name, desc, walker);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/CachePagesListViewWalker.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/CachePagesListViewWalker.java
new file mode 100644
index 0000000..1a795ad
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/CachePagesListViewWalker.java
@@ -0,0 +1,78 @@
+/*
+ * 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.managers.systemview.walker;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.systemview.view.CachePagesListView;
+import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker;
+
+/**
+ * Generated by {@code org.apache.ignite.codegen.SystemViewRowAttributeWalkerGenerator}.
+ * {@link CachePagesListView} attributes walker.
+ *
+ * @see CachePagesListView
+ */
+public class CachePagesListViewWalker implements SystemViewRowAttributeWalker<CachePagesListView> {
+ /** Filter key for attribute "cacheGroupId" */
+ public static final String CACHE_GROUP_ID_FILTER = "cacheGroupId";
+
+ /** Filter key for attribute "partitionId" */
+ public static final String PARTITION_ID_FILTER = "partitionId";
+
+ /** Filter key for attribute "bucketNumber" */
+ public static final String BUCKET_NUMBER_FILTER = "bucketNumber";
+
+ /** List of filtrable attributes. */
+ private static final List<String> FILTRABLE_ATTRS = Collections.unmodifiableList(F.asList(
+ "cacheGroupId", "partitionId", "bucketNumber"
+ ));
+
+ /** {@inheritDoc} */
+ @Override public List<String> filtrableAttributes() {
+ return FILTRABLE_ATTRS;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void visitAll(AttributeVisitor v) {
+ v.accept(0, "cacheGroupId", int.class);
+ v.accept(1, "partitionId", int.class);
+ v.accept(2, "name", String.class);
+ v.accept(3, "bucketNumber", int.class);
+ v.accept(4, "bucketSize", long.class);
+ v.accept(5, "stripesCount", int.class);
+ v.accept(6, "cachedPagesCount", int.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void visitAll(CachePagesListView row, AttributeWithValueVisitor v) {
+ v.acceptInt(0, "cacheGroupId", row.cacheGroupId());
+ v.acceptInt(1, "partitionId", row.partitionId());
+ v.accept(2, "name", String.class, row.name());
+ v.acceptInt(3, "bucketNumber", row.bucketNumber());
+ v.acceptLong(4, "bucketSize", row.bucketSize());
+ v.acceptInt(5, "stripesCount", row.stripesCount());
+ v.acceptInt(6, "cachedPagesCount", row.cachedPagesCount());
+ }
+
+ /** {@inheritDoc} */
+ @Override public int count() {
+ return 7;
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/Filtrable.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/Filtrable.java
new file mode 100644
index 0000000..4093996
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/Filtrable.java
@@ -0,0 +1,35 @@
+/*
+ * 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.managers.systemview.walker;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker;
+
+/**
+ * Annotation to mark view row attribute for a {@link SystemViewRowAttributeWalker} as filtrable.
+ *
+ * @see SystemViewRowAttributeWalker
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Filtrable {
+ // No-op.
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/PagesListViewWalker.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/PagesListViewWalker.java
new file mode 100644
index 0000000..0e42517
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/PagesListViewWalker.java
@@ -0,0 +1,68 @@
+/*
+ * 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.managers.systemview.walker;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.systemview.view.PagesListView;
+import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker;
+
+/**
+ * Generated by {@code org.apache.ignite.codegen.SystemViewRowAttributeWalkerGenerator}.
+ * {@link PagesListView} attributes walker.
+ *
+ * @see PagesListView
+ */
+public class PagesListViewWalker implements SystemViewRowAttributeWalker<PagesListView> {
+ /** Filter key for attribute "bucketNumber" */
+ public static final String BUCKET_NUMBER_FILTER = "bucketNumber";
+
+ /** List of filtrable attributes. */
+ private static final List<String> FILTRABLE_ATTRS = Collections.unmodifiableList(F.asList(
+ "bucketNumber"
+ ));
+
+ /** {@inheritDoc} */
+ @Override public List<String> filtrableAttributes() {
+ return FILTRABLE_ATTRS;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void visitAll(AttributeVisitor v) {
+ v.accept(0, "name", String.class);
+ v.accept(1, "bucketNumber", int.class);
+ v.accept(2, "bucketSize", long.class);
+ v.accept(3, "stripesCount", int.class);
+ v.accept(4, "cachedPagesCount", int.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void visitAll(PagesListView row, AttributeWithValueVisitor v) {
+ v.accept(0, "name", String.class, row.name());
+ v.acceptInt(1, "bucketNumber", row.bucketNumber());
+ v.acceptLong(2, "bucketSize", row.bucketSize());
+ v.acceptInt(3, "stripesCount", row.stripesCount());
+ v.acceptInt(4, "cachedPagesCount", row.cachedPagesCount());
+ }
+
+ /** {@inheritDoc} */
+ @Override public int count() {
+ return 5;
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index 5cf1122..13663ac 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -35,8 +35,10 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.management.MBeanServer;
import org.apache.ignite.IgniteCheckedException;
@@ -74,6 +76,7 @@ import org.apache.ignite.internal.cluster.DetachedClusterNode;
import org.apache.ignite.internal.managers.communication.GridIoPolicy;
import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage;
import org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpi;
+import org.apache.ignite.internal.managers.systemview.walker.CachePagesListViewWalker;
import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager;
import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
import org.apache.ignite.internal.processors.GridProcessorAdapter;
@@ -101,9 +104,12 @@ import org.apache.ignite.internal.processors.cache.persistence.DataRegion;
import org.apache.ignite.internal.processors.cache.persistence.DatabaseLifecycleListener;
import org.apache.ignite.internal.processors.cache.persistence.DbCheckpointListener;
import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
+import org.apache.ignite.internal.processors.cache.persistence.GridCacheOffheapManager;
import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
+import org.apache.ignite.internal.processors.cache.persistence.RowStore;
import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.PagesList;
import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetaStorage;
import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetastorageLifecycleListener;
import org.apache.ignite.internal.processors.cache.persistence.metastorage.ReadOnlyMetastorage;
@@ -171,6 +177,7 @@ import org.apache.ignite.spi.IgniteNodeValidationResult;
import org.apache.ignite.spi.discovery.DiscoveryDataBag;
import org.apache.ignite.spi.discovery.DiscoveryDataBag.GridDiscoveryData;
import org.apache.ignite.spi.discovery.DiscoveryDataBag.JoiningNodeDiscoveryData;
+import org.apache.ignite.spi.systemview.view.CachePagesListView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -200,20 +207,18 @@ import static org.apache.ignite.internal.util.IgniteUtils.doInParallel;
*/
@SuppressWarnings({"unchecked", "TypeMayBeWeakened", "deprecation"})
public class GridCacheProcessor extends GridProcessorAdapter {
- /** Invalid region configuration message. */
- private static final String INVALID_REGION_CONFIGURATION_MESSAGE = "Failed to join node " +
- "(Incompatible data region configuration [region=%s, locNodeId=%s, isPersistenceEnabled=%s, rmtNodeId=%s, isPersistenceEnabled=%s])";
-
- /** Template of message of failed node join because encryption settings are different for the same cache. */
- private static final String ENCRYPT_MISMATCH_MESSAGE = "Failed to join node to the cluster " +
- "(encryption settings are different for cache '%s' : local=%s, remote=%s.)";
-
/** */
private static final String CACHE_NAME_AND_OPERATION_FORMAT = "[cacheName=%s, operation=%s]";
/** */
private static final String CACHE_NAMES_AND_OPERATION_FORMAT = "[cacheNames=%s, operation=%s]";
+ /** System view name for page lists. */
+ public static final String CACHE_GRP_PAGE_LIST_VIEW = "cacheGroupPageLists";
+
+ /** System view description for page lists. */
+ public static final String CACHE_GRP_PAGE_LIST_VIEW_DESC = "Cache group page lists";
+
/** Enables start caches in parallel. */
private final boolean IGNITE_ALLOW_START_CACHES_IN_PARALLEL =
IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_ALLOW_START_CACHES_IN_PARALLEL, true);
@@ -594,8 +599,15 @@ public class GridCacheProcessor extends GridProcessorAdapter {
ctx.state().cacheProcessorStarted();
ctx.authentication().cacheProcessorStarted();
- }
+ ctx.systemView().registerFiltrableView(
+ CACHE_GRP_PAGE_LIST_VIEW,
+ CACHE_GRP_PAGE_LIST_VIEW_DESC,
+ new CachePagesListViewWalker(),
+ this::pagesListViewSupplier,
+ Function.identity()
+ );
+ }
/**
* @param cfg Initializes cache configuration with proper defaults.
@@ -5323,6 +5335,53 @@ public class GridCacheProcessor extends GridProcessorAdapter {
}
/**
+ * Pages list view supplier.
+ *
+ * @param filter Filter.
+ */
+ private Iterable<CachePagesListView> pagesListViewSupplier(Map<String, Object> filter) {
+ Integer cacheGrpId = (Integer)filter.get(CachePagesListViewWalker.CACHE_GROUP_ID_FILTER);
+
+ Collection<CacheGroupContext> cacheGrps;
+
+ if (cacheGrpId != null) {
+ CacheGroupContext cacheGrp = this.cacheGrps.get(cacheGrpId);
+
+ if (cacheGrp == null)
+ return Collections.emptyList();
+
+ cacheGrps = Collections.singletonList(cacheGrp);
+ }
+ else
+ cacheGrps = this.cacheGrps.values();
+
+ Integer partId = (Integer)filter.get(CachePagesListViewWalker.PARTITION_ID_FILTER);
+ Integer bucketNum = (Integer)filter.get(CachePagesListViewWalker.BUCKET_NUMBER_FILTER);
+
+ Iterable<IgniteCacheOffheapManager.CacheDataStore> dataStores =
+ F.flat(F.iterator(cacheGrps, grp -> grp.offheap().cacheDataStores(), true));
+
+ return F.flat(F.iterator(dataStores, dataStore -> {
+ RowStore rowStore = dataStore.rowStore();
+
+ if (rowStore == null || !(dataStore instanceof GridCacheOffheapManager.GridCacheDataStore))
+ return Collections.emptySet();
+
+ PagesList pagesList = (PagesList)rowStore.freeList();
+
+ if (bucketNum != null) {
+ return bucketNum >= 0 && bucketNum < pagesList.bucketsCount() ?
+ Collections.singleton(new CachePagesListView(pagesList, bucketNum, dataStore.partId())) :
+ Collections.emptyList();
+ }
+
+ return IntStream.range(0, pagesList.bucketsCount())
+ .mapToObj(bucket -> new CachePagesListView(pagesList, bucket, dataStore.partId()))
+ .collect(Collectors.toList());
+ }, true, cacheDataStore -> partId == null || cacheDataStore.partId() == partId));
+ }
+
+ /**
* Recovery lifecycle for caches.
*/
private class CacheRecoveryLifecycle implements MetastorageLifecycleListener, DatabaseLifecycleListener {
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 a1a7913..bb99e44 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
@@ -17,7 +17,6 @@
package org.apache.ignite.internal.processors.cache.persistence;
-import javax.management.InstanceNotFoundException;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
@@ -27,6 +26,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import javax.management.InstanceNotFoundException;
import org.apache.ignite.DataRegionMetrics;
import org.apache.ignite.DataRegionMetricsProvider;
import org.apache.ignite.DataStorageMetrics;
@@ -42,6 +45,7 @@ import org.apache.ignite.failure.FailureType;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
+import org.apache.ignite.internal.managers.systemview.walker.PagesListViewWalker;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.mem.DirectMemoryRegion;
import org.apache.ignite.internal.mem.IgniteOutOfMemoryException;
@@ -78,6 +82,7 @@ import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgniteInClosure;
import org.apache.ignite.lang.IgniteOutClosure;
import org.apache.ignite.mxbean.DataRegionMetricsMXBean;
+import org.apache.ignite.spi.systemview.view.PagesListView;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_REUSE_MEMORY_ON_DEACTIVATE;
@@ -94,6 +99,12 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
/** DataRegionConfiguration name reserved for internal caches. */
public static final String SYSTEM_DATA_REGION_NAME = "sysMemPlc";
+ /** System view name for page lists. */
+ public static final String DATA_REGION_PAGE_LIST_VIEW = "dataRegionPageLists";
+
+ /** System view description for page lists. */
+ public static final String DATA_REGION_PAGE_LIST_VIEW_DESC = "Data region page lists";
+
/** Minimum size of memory chunk */
private static final long MIN_PAGE_MEMORY_SIZE = 10L * 1024 * 1024;
@@ -151,6 +162,22 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
pageSize = memCfg.getPageSize();
initDataRegions(memCfg);
+
+ cctx.kernalContext().systemView().registerView(
+ DATA_REGION_PAGE_LIST_VIEW,
+ DATA_REGION_PAGE_LIST_VIEW_DESC,
+ new PagesListViewWalker(),
+ () -> {
+ Map<String, CacheFreeList> freeLists = freeListMap;
+
+ if (freeLists == null)
+ return Collections.emptyList();
+
+ return freeLists.values().stream().flatMap(fl -> IntStream.range(0, fl.bucketsCount()).mapToObj(
+ bucket -> new PagesListView(fl, bucket))).collect(Collectors.toList());
+ },
+ Function.identity()
+ );
}
/**
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 f90da40..fa6d0af 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
@@ -1830,6 +1830,51 @@ public abstract class PagesList extends DataStructure {
}
/**
+ * Pages list name.
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Buckets count.
+ */
+ public int bucketsCount() {
+ return buckets;
+ }
+
+ /**
+ * Bucket size.
+ *
+ * @param bucket Bucket.
+ */
+ public long bucketSize(int bucket) {
+ return bucketsSize[bucket].get();
+ }
+
+ /**
+ * Stripes count.
+ *
+ * @param bucket Bucket.
+ */
+ public int stripesCount(int bucket) {
+ Stripe[] stripes = getBucket(bucket);
+
+ return stripes == null ? 0 : stripes.length;
+ }
+
+ /**
+ * Cached pages count.
+ *
+ * @param bucket Bucket.
+ */
+ public int cachedPagesCount(int bucket) {
+ PagesCache pagesCache = getBucketCache(bucket, false);
+
+ return pagesCache == null ? 0 : pagesCache.size();
+ }
+
+ /**
* Singleton reuse bag.
*/
private static final class SingletonReuseBag implements ReuseBag {
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/metric/jmx/ReadOnlyDynamicMBean.java b/modules/core/src/main/java/org/apache/ignite/spi/metric/jmx/ReadOnlyDynamicMBean.java
index dc885a0..75da1e5 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/metric/jmx/ReadOnlyDynamicMBean.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/metric/jmx/ReadOnlyDynamicMBean.java
@@ -45,6 +45,8 @@ public abstract class ReadOnlyDynamicMBean implements DynamicMBean {
try {
if ("getAttribute".equals(actionName))
return getAttribute((String)params[0]);
+ else if ("invoke".equals(actionName))
+ return invoke((String)params[0], (Object[])params[1], (String[])params[2]);
}
catch (AttributeNotFoundException e) {
throw new MBeanException(e);
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/systemview/jmx/SystemViewMBean.java b/modules/core/src/main/java/org/apache/ignite/spi/systemview/jmx/SystemViewMBean.java
index 6eaab1c..6f80bd7 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/systemview/jmx/SystemViewMBean.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/systemview/jmx/SystemViewMBean.java
@@ -20,28 +20,39 @@ package org.apache.ignite.spi.systemview.jmx;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetSocketAddress;
+import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
+import javax.management.MBeanException;
import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
import javax.management.ObjectName;
+import javax.management.ReflectionException;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenMBeanAttributeInfo;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
import javax.management.openmbean.OpenMBeanInfoSupport;
+import javax.management.openmbean.OpenMBeanOperationInfo;
+import javax.management.openmbean.OpenMBeanOperationInfoSupport;
+import javax.management.openmbean.OpenMBeanParameterInfo;
+import javax.management.openmbean.OpenMBeanParameterInfoSupport;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.managers.systemview.GridSystemViewManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.spi.metric.jmx.JmxMetricExporterSpi;
import org.apache.ignite.spi.metric.jmx.ReadOnlyDynamicMBean;
+import org.apache.ignite.spi.systemview.view.FiltrableSystemView;
import org.apache.ignite.spi.systemview.view.SystemView;
-import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker.AttributeVisitor;
import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker.AttributeWithValueVisitor;
@@ -55,6 +66,9 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
/** View attribute. */
public static final String VIEWS = "views";
+ /** Filter operation name. */
+ public static final String FILTER_OPERATION = "filter";
+
/** Row id attribute name. */
public static final String ID = "systemViewRowId";
@@ -70,6 +84,9 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
/** System view type. */
private final TabularType sysViewType;
+ /** Filter field names. */
+ private final String[] filterFields;
+
/**
* @param sysView System view to export.
*/
@@ -81,6 +98,8 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
String[] fields = new String[cnt+1];
OpenType[] types = new OpenType[cnt+1];
+ List<Integer> filterFieldIdxs = new ArrayList<>(cnt);
+
sysView.walker().visitAll(new AttributeVisitor() {
@Override public <T> void accept(int idx, String name, Class<T> clazz) {
fields[idx] = name;
@@ -115,6 +134,9 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
types[idx] = SimpleType.DOUBLE;
else
types[idx] = SimpleType.STRING;
+
+ if (sysView.walker().filtrableAttributes().contains(name))
+ filterFieldIdxs.add(idx);
}
});
@@ -128,6 +150,29 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
fields,
types);
+ OpenMBeanOperationInfo[] operations = null;
+
+ if (!filterFieldIdxs.isEmpty() && sysView instanceof FiltrableSystemView) {
+ OpenMBeanParameterInfo[] params = new OpenMBeanParameterInfo[filterFieldIdxs.size()];
+
+ filterFields = new String[filterFieldIdxs.size()];
+
+ for (int i = 0; i < filterFieldIdxs.size(); i++) {
+ String fieldName = fields[filterFieldIdxs.get(i)];
+
+ filterFields[i] = fieldName;
+
+ params[i] = new OpenMBeanParameterInfoSupport(fieldName, fieldName, types[filterFieldIdxs.get(i)]);
+ }
+
+ OpenMBeanOperationInfo operation = new OpenMBeanOperationInfoSupport(FILTER_OPERATION,
+ "Filter view content", params, rowType, MBeanOperationInfo.INFO);
+
+ operations = new OpenMBeanOperationInfo[] {operation};
+ }
+ else
+ filterFields = null;
+
info = new OpenMBeanInfoSupport(
sysView.name(),
sysView.description(),
@@ -135,7 +180,7 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
new OpenMBeanAttributeInfoSupport(VIEWS, VIEWS, rowType, true, false, false)
},
null,
- null,
+ operations,
null
);
@@ -156,34 +201,30 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
if ("MBeanInfo".equals(attribute))
return getMBeanInfo();
- if (attribute.equals(VIEWS)) {
- TabularDataSupport rows = new TabularDataSupport(sysViewType);
+ if (attribute.equals(VIEWS))
+ return viewContent(null);
- AttributeToMapVisitor visitor = new AttributeToMapVisitor();
-
- try {
- int idx = 0;
-
- for (R row : sysView) {
- Map<String, Object> data = new HashMap<>();
-
- visitor.data(data);
+ throw new IllegalArgumentException("Unknown attribute " + attribute);
+ }
- sysView.walker().visitAll(row, visitor);
+ /** {@inheritDoc} */
+ @Override public Object invoke(String actName, Object[] params,
+ String[] signature) throws MBeanException, ReflectionException {
+ if (FILTER_OPERATION.equals(actName)) {
+ assert filterFields != null;
+ assert filterFields.length >= params.length;
- data.put(ID, idx++);
+ Map<String, Object> filter = U.newHashMap(params.length);
- rows.put(new CompositeDataSupport(rowType, data));
- }
- }
- catch (OpenDataException e) {
- throw new IgniteException(e);
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] != null)
+ filter.put(filterFields[i], params[i]);
}
- return rows;
+ return viewContent(filter);
}
- throw new IllegalArgumentException("Unknown attribute " + attribute);
+ return super.invoke(actName, params, signature);
}
/** {@inheritDoc} */
@@ -191,6 +232,39 @@ public class SystemViewMBean<R> extends ReadOnlyDynamicMBean {
return info;
}
+ /**
+ * Gets tabular data with system view content.
+ */
+ private TabularDataSupport viewContent(Map<String, Object> filter) {
+ TabularDataSupport rows = new TabularDataSupport(sysViewType);
+
+ AttributeToMapVisitor visitor = new AttributeToMapVisitor();
+
+ try {
+ int idx = 0;
+
+ Iterable<R> iter = filter != null && sysView instanceof FiltrableSystemView ?
+ () -> ((FiltrableSystemView<R>)sysView).iterator(filter) : sysView;
+
+ for (R row : iter) {
+ Map<String, Object> data = new HashMap<>();
+
+ visitor.data(data);
+
+ sysView.walker().visitAll(row, visitor);
+
+ data.put(ID, idx++);
+
+ rows.put(new CompositeDataSupport(rowType, data));
+ }
+ }
+ catch (OpenDataException e) {
+ throw new IgniteException(e);
+ }
+
+ return rows;
+ }
+
/** Fullfill {@code data} Map for specific row. */
private static class AttributeToMapVisitor implements AttributeWithValueVisitor {
/** Map to store data. */
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/CachePagesListView.java b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/CachePagesListView.java
new file mode 100644
index 0000000..4664442
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/CachePagesListView.java
@@ -0,0 +1,58 @@
+/*
+ * 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.spi.systemview.view;
+
+import org.apache.ignite.internal.managers.systemview.walker.Filtrable;
+import org.apache.ignite.internal.managers.systemview.walker.Order;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.PagesList;
+
+/**
+ * Pages-list representation for a {@link SystemView}.
+ */
+public class CachePagesListView extends PagesListView {
+ /** Partition id. */
+ private final int partId;
+
+ /**
+ * @param pagesList Pages list.
+ * @param bucket Bucket number.
+ */
+ public CachePagesListView(PagesList pagesList, int bucket, int partId) {
+ super(pagesList, bucket);
+
+ this.partId = partId;
+ }
+
+ /**
+ * @return Cache group id.
+ */
+ @Order
+ @Filtrable
+ public int cacheGroupId() {
+ return pagesList.groupId();
+ }
+
+ /**
+ * @return Partition id.
+ */
+ @Order(1)
+ @Filtrable
+ public int partitionId() {
+ return partId;
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/FiltrableSystemView.java b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/FiltrableSystemView.java
new file mode 100644
index 0000000..2db8c67
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/FiltrableSystemView.java
@@ -0,0 +1,34 @@
+/*
+ * 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.spi.systemview.view;
+
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * System view with filtering capabilities.
+ *
+ * @param <R> Type of the row.
+ */
+public interface FiltrableSystemView<R> extends SystemView<R> {
+ /**
+ * @param filter Filter for a view ({@code null} or empty filter means no filtering).
+ * @return Iterator for filtered system view content.
+ */
+ public Iterator<R> iterator(Map<String, Object> filter);
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/PagesListView.java b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/PagesListView.java
new file mode 100644
index 0000000..1e9274c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/PagesListView.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.spi.systemview.view;
+
+import org.apache.ignite.internal.managers.systemview.walker.Filtrable;
+import org.apache.ignite.internal.managers.systemview.walker.Order;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.PagesList;
+
+/**
+ * Pages-list representation for a {@link SystemView}.
+ */
+public class PagesListView {
+ /** Pages list. */
+ PagesList pagesList;
+
+ /** Bucket number. */
+ int bucket;
+
+ /**
+ * @param pagesList Pages list.
+ * @param bucket Bucket number.
+ */
+ public PagesListView(PagesList pagesList, int bucket) {
+ this.pagesList = pagesList;
+ this.bucket = bucket;
+ }
+
+ /**
+ * @return Pages-list name.
+ */
+ @Order(2)
+ public String name() {
+ return pagesList.name();
+ }
+
+ /**
+ * @return Bucket number.
+ * */
+ @Order(3)
+ @Filtrable
+ public int bucketNumber() {
+ return bucket;
+ }
+
+ /**
+ * @return Bucket size.
+ */
+ @Order(4)
+ public long bucketSize() {
+ return pagesList.bucketSize(bucket);
+ }
+
+ /**
+ * @return Bucket stripes count.
+ */
+ @Order(5)
+ public int stripesCount() {
+ return pagesList.stripesCount(bucket);
+ }
+
+ /**
+ * @return Count of pages cached onheap.
+ */
+ @Order(6)
+ public int cachedPagesCount() {
+ return pagesList.cachedPagesCount(bucket);
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/SystemViewRowAttributeWalker.java b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/SystemViewRowAttributeWalker.java
index 0c26997..a902442 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/SystemViewRowAttributeWalker.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/SystemViewRowAttributeWalker.java
@@ -17,6 +17,9 @@
package org.apache.ignite.spi.systemview.view;
+import java.util.Collections;
+import java.util.List;
+
/**
* Utility class for quick iteration over row properties.
*/
@@ -40,6 +43,13 @@ public interface SystemViewRowAttributeWalker<R> {
*/
public void visitAll(R row, AttributeWithValueVisitor visitor);
+ /**
+ * @return List of filtrable attributes for this system view.
+ */
+ public default List<String> filtrableAttributes() {
+ return Collections.emptyList();
+ }
+
/** Attribute visitor. */
public interface AttributeVisitor {
/**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/metric/JmxExporterSpiTest.java b/modules/core/src/test/java/org/apache/ignite/internal/metric/JmxExporterSpiTest.java
index f9222fa..8d26e58 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/metric/JmxExporterSpiTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/metric/JmxExporterSpiTest.java
@@ -36,6 +36,8 @@ import java.util.function.Consumer;
import javax.management.DynamicMBean;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanFeatureInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
@@ -48,6 +50,7 @@ import org.apache.ignite.IgniteJdbcThinDriver;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
import org.apache.ignite.cache.query.ContinuousQuery;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.ScanQuery;
@@ -59,6 +62,7 @@ import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.client.thin.ProtocolVersion;
+import org.apache.ignite.internal.managers.systemview.walker.CachePagesListViewWalker;
import org.apache.ignite.internal.metric.SystemViewSelfTest.TestPredicate;
import org.apache.ignite.internal.metric.SystemViewSelfTest.TestRunnable;
import org.apache.ignite.internal.metric.SystemViewSelfTest.TestTransformer;
@@ -85,6 +89,7 @@ import static org.apache.ignite.internal.metric.SystemViewSelfTest.TEST_TRANSFOR
import static org.apache.ignite.internal.processors.cache.CacheMetricsImpl.CACHE_METRICS;
import static org.apache.ignite.internal.processors.cache.ClusterCachesInfo.CACHES_VIEW;
import static org.apache.ignite.internal.processors.cache.ClusterCachesInfo.CACHE_GRPS_VIEW;
+import static org.apache.ignite.internal.processors.cache.GridCacheProcessor.CACHE_GRP_PAGE_LIST_VIEW;
import static org.apache.ignite.internal.processors.cache.GridCacheUtils.cacheGroupId;
import static org.apache.ignite.internal.processors.cache.GridCacheUtils.cacheId;
import static org.apache.ignite.internal.processors.cache.transactions.IgniteTxManager.TXS_MON_LIST;
@@ -100,6 +105,7 @@ import static org.apache.ignite.internal.processors.service.IgniteServiceProcess
import static org.apache.ignite.internal.processors.task.GridTaskProcessor.TASKS_VIEW;
import static org.apache.ignite.internal.util.IgniteUtils.toStringSafe;
import static org.apache.ignite.spi.metric.jmx.MetricRegistryMBean.searchHistogram;
+import static org.apache.ignite.spi.systemview.jmx.SystemViewMBean.FILTER_OPERATION;
import static org.apache.ignite.spi.systemview.jmx.SystemViewMBean.VIEWS;
import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
@@ -464,6 +470,34 @@ public class JmxExporterSpiTest extends AbstractExporterSpiTest {
}
/** */
+ public TabularDataSupport filteredSystemView(IgniteEx g, String name, Map<String, Object> filter) {
+ try {
+ DynamicMBean mbean = mbean(g, VIEWS, name);
+
+ MBeanOperationInfo[] opers = mbean.getMBeanInfo().getOperations();
+
+ assertEquals(1, opers.length);
+
+ assertEquals(FILTER_OPERATION, opers[0].getName());
+
+ MBeanParameterInfo[] paramInfo = opers[0].getSignature();
+
+ Object params[] = new Object[paramInfo.length];
+ String signature[] = new String[paramInfo.length];
+
+ for (int i = 0; i < paramInfo.length; i++) {
+ params[i] = filter.get(paramInfo[i].getName());
+ signature[i] = paramInfo[i].getType();
+ }
+
+ return (TabularDataSupport)mbean.invoke(FILTER_OPERATION, params, signature);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** */
public DynamicMBean mbean(IgniteEx g, String grp, String name) throws MalformedObjectNameException {
ObjectName mbeanName = U.makeMBeanName(g.name(), grp, name);
@@ -857,6 +891,34 @@ public class JmxExporterSpiTest extends AbstractExporterSpiTest {
}
/** */
+ @Test
+ public void testPagesList() throws Exception {
+ String cacheName = "cacheFL";
+
+ IgniteCache<Integer, Integer> cache = ignite.getOrCreateCache(new CacheConfiguration<Integer, Integer>()
+ .setName(cacheName).setAffinity(new RendezvousAffinityFunction().setPartitions(2)));
+
+ // Put some data to cache to init cache partitions.
+ for (int i = 0; i < 10; i++)
+ cache.put(i, i);
+
+ TabularDataSupport view = filteredSystemView(ignite, CACHE_GRP_PAGE_LIST_VIEW, U.map(
+ CachePagesListViewWalker.CACHE_GROUP_ID_FILTER, cacheId(cacheName),
+ CachePagesListViewWalker.PARTITION_ID_FILTER, 0,
+ CachePagesListViewWalker.BUCKET_NUMBER_FILTER, 0
+ ));
+
+ assertEquals(1, view.size());
+
+ view = filteredSystemView(ignite, CACHE_GRP_PAGE_LIST_VIEW, U.map(
+ CachePagesListViewWalker.CACHE_GROUP_ID_FILTER, cacheId(cacheName),
+ CachePagesListViewWalker.BUCKET_NUMBER_FILTER, 0
+ ));
+
+ assertEquals(2, view.size());
+ }
+
+ /** */
private void createTestHistogram(MetricRegistry mreg) {
long[] bounds = new long[] {50, 500};
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java
index 22bf15a..283e447 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java
@@ -41,6 +41,7 @@ import org.apache.ignite.IgniteJdbcThinDriver;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
import org.apache.ignite.cache.query.ContinuousQuery;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.ScanQuery;
@@ -52,13 +53,20 @@ import org.apache.ignite.compute.ComputeJobResultPolicy;
import org.apache.ignite.compute.ComputeTask;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.ClientConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.client.thin.ProtocolVersion;
+import org.apache.ignite.internal.managers.systemview.walker.CachePagesListViewWalker;
+import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
+import org.apache.ignite.spi.systemview.view.CachePagesListView;
+import org.apache.ignite.spi.systemview.view.PagesListView;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext;
import org.apache.ignite.internal.processors.service.DummyService;
import org.apache.ignite.internal.util.StripedExecutor;
import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.lang.IgniteCallable;
import org.apache.ignite.lang.IgniteClosure;
@@ -71,6 +79,7 @@ import org.apache.ignite.spi.systemview.view.ClientConnectionView;
import org.apache.ignite.spi.systemview.view.ClusterNodeView;
import org.apache.ignite.spi.systemview.view.ComputeTaskView;
import org.apache.ignite.spi.systemview.view.ContinuousQueryView;
+import org.apache.ignite.spi.systemview.view.FiltrableSystemView;
import org.apache.ignite.spi.systemview.view.ScanQueryView;
import org.apache.ignite.spi.systemview.view.ServiceView;
import org.apache.ignite.spi.systemview.view.StripedExecutorTaskView;
@@ -89,8 +98,10 @@ import static org.apache.ignite.internal.managers.systemview.GridSystemViewManag
import static org.apache.ignite.internal.managers.systemview.ScanQuerySystemView.SCAN_QRY_SYS_VIEW;
import static org.apache.ignite.internal.processors.cache.ClusterCachesInfo.CACHES_VIEW;
import static org.apache.ignite.internal.processors.cache.ClusterCachesInfo.CACHE_GRPS_VIEW;
+import static org.apache.ignite.internal.processors.cache.GridCacheProcessor.CACHE_GRP_PAGE_LIST_VIEW;
import static org.apache.ignite.internal.processors.cache.GridCacheUtils.cacheGroupId;
import static org.apache.ignite.internal.processors.cache.GridCacheUtils.cacheId;
+import static org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager.DATA_REGION_PAGE_LIST_VIEW;
import static org.apache.ignite.internal.processors.cache.transactions.IgniteTxManager.TXS_MON_LIST;
import static org.apache.ignite.internal.processors.continuous.GridContinuousProcessor.CQ_SYS_VIEW;
import static org.apache.ignite.internal.processors.odbc.ClientListenerProcessor.CLI_CONN_VIEW;
@@ -983,6 +994,95 @@ public class SystemViewSelfTest extends GridCommonAbstractTest {
}
}
+ /** */
+ @Test
+ public void testPagesList() throws Exception {
+ cleanPersistenceDir();
+
+ try (IgniteEx ignite = startGrid(getConfiguration()
+ .setDataStorageConfiguration(
+ new DataStorageConfiguration().setDataRegionConfigurations(
+ new DataRegionConfiguration().setName("dr0").setMaxSize(100L * 1024 * 1024),
+ new DataRegionConfiguration().setName("dr1").setMaxSize(100L * 1024 * 1024)
+ .setPersistenceEnabled(true)
+ )))) {
+ ignite.cluster().active(true);
+
+ GridCacheDatabaseSharedManager dbMgr = (GridCacheDatabaseSharedManager)ignite.context().cache().context()
+ .database();
+
+ int pageSize = dbMgr.pageSize();
+
+ dbMgr.enableCheckpoints(false).get();
+
+ for (int i = 0; i < 2; i++) {
+ IgniteCache<Object, Object> cache = ignite.getOrCreateCache(new CacheConfiguration<>("cache" + i)
+ .setDataRegionName("dr" + i).setAffinity(new RendezvousAffinityFunction().setPartitions(2)));
+
+ int key = 0;
+
+ // Fill up different free-list buckets.
+ for (int j = 0; j < pageSize / 2; j++)
+ cache.put(key++, new byte[j + 1]);
+
+ // Put some pages to one bucket to overflow pages cache.
+ for (int j = 0; j < 1000; j++)
+ cache.put(key++, new byte[pageSize / 2]);
+ }
+
+ long dr0flPages = 0;
+ int dr0flStripes = 0;
+
+ SystemView<PagesListView> dataRegionPageLists = ignite.context().systemView().view(DATA_REGION_PAGE_LIST_VIEW);
+
+ for (PagesListView pagesListView : dataRegionPageLists) {
+ if (pagesListView.name().startsWith("dr0")) {
+ dr0flPages += pagesListView.bucketSize();
+ dr0flStripes += pagesListView.stripesCount();
+ }
+ }
+
+ assertTrue(dr0flPages > 0);
+ assertTrue(dr0flStripes > 0);
+
+ SystemView<CachePagesListView> cacheGrpPageLists = ignite.context().systemView().view(CACHE_GRP_PAGE_LIST_VIEW);
+
+ long dr1flPages = 0;
+ int dr1flStripes = 0;
+ int dr1flCached = 0;
+
+ for (CachePagesListView pagesListView : cacheGrpPageLists) {
+ if (pagesListView.cacheGroupId() == cacheId("cache1")) {
+ dr1flPages += pagesListView.bucketSize();
+ dr1flStripes += pagesListView.stripesCount();
+ dr1flCached += pagesListView.cachedPagesCount();
+ }
+ }
+
+ assertTrue(dr1flPages > 0);
+ assertTrue(dr1flStripes > 0);
+ assertTrue(dr1flCached > 0);
+
+ // Test filtering.
+ assertTrue(cacheGrpPageLists instanceof FiltrableSystemView);
+
+ Iterator<CachePagesListView> iter = ((FiltrableSystemView<CachePagesListView>)cacheGrpPageLists).iterator(U.map(
+ CachePagesListViewWalker.CACHE_GROUP_ID_FILTER, cacheId("cache1"),
+ CachePagesListViewWalker.PARTITION_ID_FILTER, 0,
+ CachePagesListViewWalker.BUCKET_NUMBER_FILTER, 0
+ ));
+
+ assertEquals(1, F.size(iter));
+
+ iter = ((FiltrableSystemView<CachePagesListView>)cacheGrpPageLists).iterator(U.map(
+ CachePagesListViewWalker.CACHE_GROUP_ID_FILTER, cacheId("cache1"),
+ CachePagesListViewWalker.BUCKET_NUMBER_FILTER, 0
+ ));
+
+ assertEquals(2, F.size(iter));
+ }
+ }
+
/** Test node filter. */
public static class TestNodeFilter implements IgnitePredicate<ClusterNode> {
/** {@inheritDoc} */
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java
index 1962342..753a1ab 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SqlSystemIndex.java
@@ -19,9 +19,11 @@ package org.apache.ignite.internal.processors.query.h2.sys;
import java.util.Iterator;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2Cursor;
+import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
import org.h2.index.Cursor;
+import org.h2.index.IndexCondition;
import org.h2.index.IndexType;
import org.h2.message.DbException;
import org.h2.result.Row;
@@ -82,14 +84,22 @@ public class SqlSystemIndex extends BaseIndex {
/** {@inheritDoc} */
@Override public double getCost(Session ses, int[] masks, TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColsSet) {
- long rowCnt = getRowCountApproximation();
+ double colsCost = getRowCountApproximation();
- double baseCost = getCostRangeIndex(masks, rowCnt, filters, filter, sortOrder, false, allColsSet);
+ if (masks != null) {
+ for (Column col : columns) {
+ // We can effictivly use only EQUALITY condition in system views.
+ if ((masks[col.getColumnId()] & IndexCondition.EQUALITY) != 0)
+ colsCost /= 2;
+ }
+ }
+
+ double idxCost = Constants.COST_ROW_OFFSET + colsCost;
if (((SystemViewH2Adapter)table).view.isDistributed())
- baseCost = baseCost * DISTRIBUTED_MUL;
+ idxCost *= DISTRIBUTED_MUL;
- return baseCost;
+ return idxCost;
}
/** {@inheritDoc} */
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SystemViewH2Adapter.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SystemViewH2Adapter.java
index 91e120b..12f36b8 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SystemViewH2Adapter.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/SystemViewH2Adapter.java
@@ -67,17 +67,19 @@ public class SystemViewH2Adapter extends TableBase {
indexes = new ArrayList<>();
indexes.add(scanIdx);
- for (String index : view.getIndexes()) {
- String[] indexedCols = index.split(",");
+ if (view.getIndexes() != null) {
+ for (String index : view.getIndexes()) {
+ String[] indexedCols = index.split(",");
- Column[] cols = new Column[indexedCols.length];
+ Column[] cols = new Column[indexedCols.length];
- for (int i = 0; i < indexedCols.length; i++)
- cols[i] = getColumn(indexedCols[i]);
+ for (int i = 0; i < indexedCols.length; i++)
+ cols[i] = getColumn(indexedCols[i]);
- SqlSystemIndex idx = new SqlSystemIndex(this, cols);
+ SqlSystemIndex idx = new SqlSystemIndex(this, cols);
- indexes.add(idx);
+ indexes.add(idx);
+ }
}
}
@@ -149,7 +151,7 @@ public class SystemViewH2Adapter extends TableBase {
/** {@inheritDoc} */
@Override public long getRowCountApproximation() {
- return view.getRowCount();
+ return view.getRowCountApproximation();
}
/** {@inheritDoc} */
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractLocalSystemView.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractLocalSystemView.java
index ef1d329..6c3e14a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractLocalSystemView.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractLocalSystemView.java
@@ -51,7 +51,6 @@ public abstract class SqlAbstractLocalSystemView extends SqlAbstractSystemView {
assert tblName != null;
assert cols != null;
- assert indexes != null;
}
/**
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractSystemView.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractSystemView.java
index 79d6225..1a5e1ca 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractSystemView.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlAbstractSystemView.java
@@ -105,6 +105,11 @@ public abstract class SqlAbstractSystemView implements SqlSystemView {
}
/** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ return getRowCount();
+ }
+
+ /** {@inheritDoc} */
@Override public boolean canGetRowCount() {
return false;
}
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemView.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemView.java
index 93fdfa0..86d249c 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemView.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sys/view/SqlSystemView.java
@@ -62,6 +62,11 @@ public interface SqlSystemView {
public long getRowCount();
/**
+ * Gets approximated row count (required to build execution plan).
+ */
+ public long getRowCountApproximation();
+
+ /**
* Check if the row count can be retrieved quickly.
*
* @return true if it can
diff --git a/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/FiltrableSystemViewLocal.java b/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/FiltrableSystemViewLocal.java
new file mode 100644
index 0000000..a354e94
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/FiltrableSystemViewLocal.java
@@ -0,0 +1,98 @@
+/*
+ * 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.spi.systemview;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
+import org.apache.ignite.internal.processors.query.IgniteSQLException;
+import org.apache.ignite.internal.processors.query.h2.sys.view.SqlSystemViewColumnCondition;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.systemview.view.FiltrableSystemView;
+import org.apache.ignite.spi.systemview.view.SystemView;
+import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker.AttributeVisitor;
+import org.h2.result.SearchRow;
+
+/**
+ * Filtrable SQL system view to export {@link SystemView} data.
+ */
+public class FiltrableSystemViewLocal<R> extends SystemViewLocal<R> {
+ /** View attribute names. */
+ private final String[] attributeNames;
+
+ /** View attribute classes. */
+ private final Class<?>[] attributeClasses;
+
+ /**
+ * @param ctx Kernal context.
+ * @param sysView View to export.
+ */
+ public FiltrableSystemViewLocal(GridKernalContext ctx, SystemView<R> sysView) {
+ super(ctx, sysView, indexes(sysView));
+
+ assert sysView instanceof FiltrableSystemView;
+
+ attributeNames = new String[sysView.walker().count()];
+ attributeClasses = new Class<?>[sysView.walker().count()];
+
+ sysView.walker().visitAll(new AttributeVisitor() {
+ @Override public <T> void accept(int idx, String name, Class<T> clazz) {
+ attributeNames[idx] = name;
+ attributeClasses[idx] = U.box(clazz);
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Iterator<R> viewIterator(SearchRow first, SearchRow last) {
+ Map<String, Object> filter = new HashMap<>();
+
+ for (int i = 0; i < cols.length; i++) {
+ SqlSystemViewColumnCondition cond = SqlSystemViewColumnCondition.forColumn(i, first, last);
+
+ if (cond.isEquality()) {
+ Object val = cond.valueForEquality().getObject();
+
+ if (attributeClasses[i].isInstance(val))
+ filter.put(attributeNames[i], val);
+ else {
+ throw new IgniteSQLException("Unexpected filter value type [column=" + cols[i] +
+ ", actual=" + val.getClass().getSimpleName() +
+ ", expected=" + attributeClasses[i].getSimpleName(),
+ IgniteQueryErrorCode.CONVERSION_FAILED);
+ }
+ }
+ }
+
+ return ((FiltrableSystemView<R>)sysView).iterator(filter);
+ }
+
+ /**
+ * Extract indexes for specific {@link SystemView}.
+ *
+ * @param sysView System view.
+ * @return Indexes array for {@code sysView}.
+ */
+ private static String[] indexes(SystemView<?> sysView) {
+ return new String[] {sysView.walker().filtrableAttributes().stream().map(SystemViewLocal::sqlName)
+ .collect(Collectors.joining(","))};
+ }
+}
diff --git a/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SqlViewExporterSpi.java b/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SqlViewExporterSpi.java
index 301bd9f..c10a01a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SqlViewExporterSpi.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SqlViewExporterSpi.java
@@ -27,6 +27,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.spi.IgniteSpiAdapter;
import org.apache.ignite.spi.IgniteSpiContext;
import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.systemview.view.FiltrableSystemView;
import org.apache.ignite.spi.systemview.view.SystemView;
import org.jetbrains.annotations.Nullable;
@@ -77,7 +78,8 @@ public class SqlViewExporterSpi extends IgniteSpiAdapter implements SystemViewEx
GridKernalContext ctx = ((IgniteEx)ignite()).context();
- SystemViewLocal<?> view = new SystemViewLocal<>(ctx, sysView);
+ SystemViewLocal<?> view = sysView instanceof FiltrableSystemView ?
+ new FiltrableSystemViewLocal<>(ctx, sysView) : new SystemViewLocal<>(ctx, sysView);
mgr.createSystemView(SCHEMA_SYS, view);
}
diff --git a/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SystemViewLocal.java b/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SystemViewLocal.java
index aba538d8..fa3c17a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SystemViewLocal.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/spi/systemview/SystemViewLocal.java
@@ -26,9 +26,9 @@ import java.util.Objects;
import java.util.UUID;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.processors.metric.impl.MetricUtils;
-import org.apache.ignite.spi.systemview.view.SystemView;
import org.apache.ignite.internal.processors.query.h2.sys.view.SqlAbstractLocalSystemView;
import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.spi.systemview.view.SystemView;
import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker.AttributeVisitor;
import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker.AttributeWithValueVisitor;
import org.h2.engine.Session;
@@ -54,21 +54,37 @@ import org.h2.value.ValueUuid;
*/
public class SystemViewLocal<R> extends SqlAbstractLocalSystemView {
/** System view for export. */
- private final SystemView<R> sysView;
+ protected final SystemView<R> sysView;
/**
* @param ctx Kernal context.
* @param sysView View to export.
+ * @param indexes Indexed fields.
*/
- public SystemViewLocal(GridKernalContext ctx, SystemView<R> sysView) {
- super(sqlName(sysView.name()), sysView.description(), ctx, columnsList(sysView));
+ protected SystemViewLocal(GridKernalContext ctx, SystemView<R> sysView, String[] indexes) {
+ super(sqlName(sysView.name()), sysView.description(), ctx, indexes, columnsList(sysView));
this.sysView = sysView;
}
+ /**
+ * @param ctx Kernal context.
+ * @param sysView View to export.
+ */
+ public SystemViewLocal(GridKernalContext ctx, SystemView<R> sysView) {
+ this(ctx, sysView, null);
+ }
+
+ /**
+ * System view iterator.
+ */
+ protected Iterator<R> viewIterator(SearchRow first, SearchRow last) {
+ return sysView.iterator();
+ }
+
/** {@inheritDoc} */
@Override public Iterator<Row> getRows(Session ses, SearchRow first, SearchRow last) {
- Iterator<R> rows = sysView.iterator();
+ Iterator<R> rows = viewIterator(first, last);
return new Iterator<Row>() {
@Override public boolean hasNext() {
@@ -161,7 +177,7 @@ public class SystemViewLocal<R> extends SqlAbstractLocalSystemView {
*
* @param sysView System view.
* @param <R> Row type.
- * @return SQL column array for {@code rowClass}.
+ * @return SQL column array for {@code sysView}.
*/
private static <R> Column[] columnsList(SystemView<R> sysView) {
Column[] cols = new Column[sysView.walker().count()];
@@ -214,6 +230,13 @@ public class SystemViewLocal<R> extends SqlAbstractLocalSystemView {
}
/** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ // getRowCount() method is not really fast, for some system views it's required to iterate over elements to
+ // calculate size, so it's more safe to use constant here.
+ return DEFAULT_ROW_COUNT_APPROXIMATION;
+ }
+
+ /** {@inheritDoc} */
@Override public boolean canGetRowCount() {
return true;
}
@@ -228,7 +251,7 @@ public class SystemViewLocal<R> extends SqlAbstractLocalSystemView {
* @param name Name to convert.
* @return SQL compatible name.
*/
- public static String sqlName(String name) {
+ protected static String sqlName(String name) {
return name
.replaceAll("([A-Z])", "_$1")
.replaceAll('\\' + MetricUtils.SEPARATOR, "_").toUpperCase();
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
index dc39ec2..3a6652d 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
@@ -35,6 +35,7 @@ import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteJdbcThinDriver;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
import org.apache.ignite.cache.query.ContinuousQuery;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.ScanQuery;
@@ -50,6 +51,7 @@ import org.apache.ignite.internal.metric.AbstractExporterSpiTest;
import org.apache.ignite.internal.metric.SystemViewSelfTest.TestPredicate;
import org.apache.ignite.internal.metric.SystemViewSelfTest.TestRunnable;
import org.apache.ignite.internal.metric.SystemViewSelfTest.TestTransformer;
+import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.service.DummyService;
import org.apache.ignite.internal.util.StripedExecutor;
import org.apache.ignite.lang.IgniteBiTuple;
@@ -90,7 +92,11 @@ public class SqlViewExporterSpiTest extends AbstractExporterSpiTest {
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+ cfg.setConsistentId(igniteInstanceName);
+
cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+ .setDataRegionConfigurations(
+ new DataRegionConfiguration().setName("in-memory").setMaxSize(100L * 1024 * 1024))
.setDefaultDataRegionConfiguration(
new DataRegionConfiguration()
.setPersistenceEnabled(true)));
@@ -417,7 +423,9 @@ public class SqlViewExporterSpiTest extends AbstractExporterSpiTest {
"TRANSACTIONS",
"CONTINUOUS_QUERIES",
"STRIPED_THREADPOOL_QUEUE",
- "DATASTREAM_THREADPOOL_QUEUE"
+ "DATASTREAM_THREADPOOL_QUEUE",
+ "DATA_REGION_PAGE_LISTS",
+ "CACHE_GROUP_PAGE_LISTS"
));
Set<String> actViews = new HashSet<>();
@@ -835,6 +843,82 @@ public class SqlViewExporterSpiTest extends AbstractExporterSpiTest {
}
}
+ /** */
+ @Test
+ public void testPagesList() throws Exception {
+ String cacheName = "cacheFL";
+
+ IgniteCache<Integer, byte[]> cache = ignite0.getOrCreateCache(new CacheConfiguration<Integer, byte[]>()
+ .setName(cacheName).setAffinity(new RendezvousAffinityFunction().setPartitions(1)));
+
+ GridCacheDatabaseSharedManager dbMgr = (GridCacheDatabaseSharedManager)ignite0.context().cache().context()
+ .database();
+
+ int pageSize = dbMgr.pageSize();
+
+ try {
+ dbMgr.enableCheckpoints(false).get();
+
+ int key = 0;
+
+ // Fill up different free-list buckets.
+ for (int j = 0; j < pageSize / 2; j++)
+ cache.put(key++, new byte[j + 1]);
+
+ // Put some pages to one bucket to overflow pages cache.
+ for (int j = 0; j < 1000; j++)
+ cache.put(key++, new byte[pageSize / 2]);
+
+ // Test filtering by 3 columns.
+ assertFalse(execute(ignite0, "SELECT * FROM SYS.CACHE_GROUP_PAGE_LISTS WHERE BUCKET_NUMBER = 0 " +
+ "AND PARTITION_ID = 0 AND CACHE_GROUP_ID = ?", cacheId(cacheName)).isEmpty());
+
+ // Test filtering with invalid cache group id.
+ assertTrue(execute(ignite0, "SELECT * FROM SYS.CACHE_GROUP_PAGE_LISTS WHERE CACHE_GROUP_ID = ?", -1)
+ .isEmpty());
+
+ // Test filtering with invalid partition id.
+ assertTrue(execute(ignite0, "SELECT * FROM SYS.CACHE_GROUP_PAGE_LISTS WHERE PARTITION_ID = ?", -1)
+ .isEmpty());
+
+ // Test filtering with invalid bucket number.
+ assertTrue(execute(ignite0, "SELECT * FROM SYS.CACHE_GROUP_PAGE_LISTS WHERE BUCKET_NUMBER = -1")
+ .isEmpty());
+
+ assertFalse(execute(ignite0, "SELECT * FROM SYS.CACHE_GROUP_PAGE_LISTS WHERE BUCKET_SIZE > 0 " +
+ "AND CACHE_GROUP_ID = ?", cacheId(cacheName)).isEmpty());
+
+ assertFalse(execute(ignite0, "SELECT * FROM SYS.CACHE_GROUP_PAGE_LISTS WHERE STRIPES_COUNT > 0 " +
+ "AND CACHE_GROUP_ID = ?", cacheId(cacheName)).isEmpty());
+
+ assertFalse(execute(ignite0, "SELECT * FROM SYS.CACHE_GROUP_PAGE_LISTS WHERE CACHED_PAGES_COUNT > 0 " +
+ "AND CACHE_GROUP_ID = ?", cacheId(cacheName)).isEmpty());
+
+ assertFalse(execute(ignite0, "SELECT * FROM SYS.DATA_REGION_PAGE_LISTS WHERE NAME LIKE 'in-memory%'")
+ .isEmpty());
+
+ assertEquals(0L, execute(ignite0, "SELECT COUNT(*) FROM SYS.DATA_REGION_PAGE_LISTS " +
+ "WHERE NAME LIKE 'in-memory%' AND BUCKET_SIZE > 0").get(0).get(0));
+ }
+ finally {
+ dbMgr.enableCheckpoints(true).get();
+ }
+
+ ignite0.cluster().active(false);
+
+ ignite0.cluster().active(true);
+
+ IgniteCache<Integer, Integer> cacheInMemory = ignite0.getOrCreateCache(new CacheConfiguration<Integer, Integer>()
+ .setName("cacheFLInMemory").setDataRegionName("in-memory"));
+
+ cacheInMemory.put(0, 0);
+
+ // After activation/deactivation new view for data region pages lists should be created, check that new view
+ // correctly reflects changes in free-lists.
+ assertFalse(execute(ignite0, "SELECT * FROM SYS.DATA_REGION_PAGE_LISTS WHERE NAME LIKE 'in-memory%' AND " +
+ "BUCKET_SIZE > 0").isEmpty());
+ }
+
/**
* Execute query on given node.
*