You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by se...@apache.org on 2017/02/16 11:30:31 UTC
[2/2] ignite git commit: Inline offheap indexes (simple types +
String).
Inline offheap indexes (simple types + String).
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/8f836cb0
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/8f836cb0
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/8f836cb0
Branch: refs/heads/ignite-3477
Commit: 8f836cb0efbda3805672788be911131d46dde9b6
Parents: 7663c22
Author: Konstantin Dudkov <kd...@ya.ru>
Authored: Thu Feb 16 14:18:05 2017 +0300
Committer: Konstantin Dudkov <kd...@ya.ru>
Committed: Thu Feb 16 14:25:32 2017 +0300
----------------------------------------------------------------------
.../benchmarks/jmh/tree/BPlusTreeBenchmark.java | 13 +-
.../apache/ignite/IgniteSystemProperties.java | 7 +
.../org/apache/ignite/cache/QueryIndex.java | 21 ++
.../configuration/CacheConfiguration.java | 35 ++-
.../internal/pagemem/wal/record/WALRecord.java | 5 +-
.../delta/MetaPageInitRootInlineRecord.java | 62 +++++
.../record/delta/MetaPageInitRootRecord.java | 3 +-
.../cache/database/MetadataStorage.java | 15 +-
.../cache/database/tree/BPlusTree.java | 72 ++++-
.../cache/database/tree/io/BPlusIO.java | 3 +-
.../cache/database/tree/io/BPlusInnerIO.java | 24 +-
.../cache/database/tree/io/BPlusLeafIO.java | 9 +-
.../cache/database/tree/io/BPlusMetaIO.java | 45 ++-
.../cache/database/tree/io/DataPageIO.java | 4 +-
.../cache/database/tree/io/DataPagePayload.java | 2 +-
.../cache/database/tree/io/PageIO.java | 60 ++++
.../query/GridQueryIndexDescriptor.java | 7 +
.../processors/query/GridQueryProcessor.java | 47 +++-
.../processors/query/h2/IgniteH2Indexing.java | 23 +-
.../processors/query/h2/database/H2Tree.java | 57 +++-
.../query/h2/database/H2TreeIndex.java | 236 +++++++++++++++-
.../query/h2/database/InlineIndexHelper.java | 279 +++++++++++++++++++
.../query/h2/database/io/H2ExtrasInnerIO.java | 135 +++++++++
.../query/h2/database/io/H2ExtrasLeafIO.java | 132 +++++++++
.../processors/query/h2/opt/GridH2Row.java | 2 +-
.../processors/query/h2/opt/GridH2Table.java | 3 +-
.../h2/GridIndexingSpiAbstractSelfTest.java | 5 +
.../query/h2/database/H2TreeIndexTest.java | 59 ++++
.../h2/database/InlineIndexHelperTest.java | 46 +++
29 files changed, 1314 insertions(+), 97 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
index d1bca73..7355850 100644
--- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
+++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
@@ -17,7 +17,6 @@
package org.apache.ignite.internal.benchmarks.jmh.tree;
-import java.nio.ByteBuffer;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;
@@ -269,12 +268,7 @@ public class BPlusTreeBenchmark extends JmhAbstractBenchmark {
throws IgniteCheckedException {
Long row = srcIo.getLookupRow(null, src, srcIdx);
- store(dst, dstIdx, row, null);
- }
-
- /** {@inheritDoc} */
- @Override public void storeByOffset(ByteBuffer buf, int off, Long row) throws IgniteCheckedException {
- throw new UnsupportedOperationException();
+ store(dst, dstIdx, row, null, false);
}
/** {@inheritDoc} */
@@ -308,11 +302,6 @@ public class BPlusTreeBenchmark extends JmhAbstractBenchmark {
}
/** {@inheritDoc} */
- @Override public void storeByOffset(ByteBuffer buf, int off, Long row) throws IgniteCheckedException {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
@Override public void storeByOffset(long pageAddr, int off, Long row) {
PageUtils.putLong(pageAddr, off, row);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index b229729..504b589 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -540,6 +540,13 @@ public final class IgniteSystemProperties {
public static final String IGNITE_UNWRAP_BINARY_FOR_INDEXING_SPI = "IGNITE_UNWRAP_BINARY_FOR_INDEXING_SPI";
/**
+ * System property to specify maximum payload size in bytes for {@code H2TreeIndex}.
+ * <p>
+ * Defaults to {@code 0}, meaning that inline index store is disabled.
+ */
+ public static final String IGNITE_MAX_INDEX_PAYLOAD_SIZE = "IGNITE_MAX_INDEX_PAYLOAD_SIZE";
+
+ /**
* Enforces singleton.
*/
private IgniteSystemProperties() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
index af11999..bbe2872 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
@@ -40,6 +40,9 @@ public class QueryIndex implements Serializable {
/** */
private QueryIndexType type;
+ /** */
+ private int inlineSize = -1;
+
/**
* Creates an empty index. Should be populated via setters.
*/
@@ -224,4 +227,22 @@ public class QueryIndex implements Serializable {
public void setIndexType(QueryIndexType type) {
this.type = type;
}
+
+ /**
+ * Gets inline size.
+ *
+ * @return inline size.
+ */
+ public int getInlineSize() {
+ return inlineSize;
+ }
+
+ /**
+ * Sets inline size.
+ *
+ * @param inlineSize Inline size.
+ */
+ public void setInlineSize(int inlineSize) {
+ this.inlineSize = inlineSize;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index b3be1cf..6c56fc5 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -2456,10 +2456,11 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
*
* @param idxName Index name.
* @param type Index type.
+ * @param inlineSize Inline size.
* @return Index descriptor.
*/
- public IndexDescriptor addIndex(String idxName, GridQueryIndexType type) {
- IndexDescriptor idx = new IndexDescriptor(type);
+ public IndexDescriptor addIndex(String idxName, GridQueryIndexType type, int inlineSize) {
+ IndexDescriptor idx = new IndexDescriptor(type, inlineSize);
if (indexes.put(idxName, idx) != null)
throw new CacheException("Index with name '" + idxName + "' already exists.");
@@ -2468,6 +2469,17 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
}
/**
+ * Adds index.
+ *
+ * @param idxName Index name.
+ * @param type Index type.
+ * @return Index descriptor.
+ */
+ public IndexDescriptor addIndex(String idxName, GridQueryIndexType type) {
+ return addIndex(idxName, type, -1);
+ }
+
+ /**
* Adds field to index.
*
* @param idxName Index name.
@@ -2594,13 +2606,25 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
/** */
private final GridQueryIndexType type;
+ /** */
+ private final int inlineSize;
+
/**
* @param type Type.
+ * @param inlineSize Inline size.
*/
- private IndexDescriptor(GridQueryIndexType type) {
+ private IndexDescriptor(GridQueryIndexType type, int inlineSize) {
assert type != null;
this.type = type;
+ this.inlineSize = inlineSize;
+ }
+
+ /**
+ * @param type Type.
+ */
+ private IndexDescriptor(GridQueryIndexType type) {
+ this(type, -1);
}
/** {@inheritDoc} */
@@ -2642,6 +2666,11 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
}
/** {@inheritDoc} */
+ @Override public int inlineSize() {
+ return inlineSize;
+ }
+
+ /** {@inheritDoc} */
@Override public String toString() {
return S.toString(IndexDescriptor.class, this);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
index f761f68..9c2c88a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
@@ -157,7 +157,10 @@ public abstract class WALRecord {
SWITCH_SEGMENT_RECORD,
/** */
- DATA_PAGE_UPDATE_RECORD
+ DATA_PAGE_UPDATE_RECORD,
+
+ /** init */
+ BTREE_META_PAGE_INIT_ROOT2
;
/** */
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java
new file mode 100644
index 0000000..212f5b9
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.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.pagemem.wal.record.delta;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusMetaIO;
+
+/**
+ *
+ */
+public class MetaPageInitRootInlineRecord extends MetaPageInitRootRecord {
+
+ /** */
+ private final int inlineSize;
+
+ /**
+ * @param cacheId
+ * @param pageId Meta page ID.
+ * @param rootId
+ * @param inlineSize Inline size.
+ */
+ public MetaPageInitRootInlineRecord(int cacheId, long pageId, long rootId, int inlineSize) {
+ super(cacheId, pageId, rootId);
+ this.inlineSize = inlineSize;
+ }
+
+ /**
+ * @return Inline size.
+ */
+ public int inlineSize() {
+ return inlineSize;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
+ BPlusMetaIO io = BPlusMetaIO.VERSIONS.forPage(pageAddr);
+
+ io.initRoot(pageAddr, rootId, pageMem.pageSize());
+ io.setInlineSize(pageAddr, inlineSize);
+ }
+
+ /** {@inheritDoc} */
+ @Override public RecordType type() {
+ return RecordType.BTREE_META_PAGE_INIT_ROOT2;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
index 4d56db0..280310f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
@@ -26,7 +26,7 @@ import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusMetaIO;
*/
public class MetaPageInitRootRecord extends PageDeltaRecord {
/** */
- private long rootId;
+ protected long rootId;
/**
* @param pageId Meta page ID.
@@ -44,6 +44,7 @@ public class MetaPageInitRootRecord extends PageDeltaRecord {
BPlusMetaIO io = BPlusMetaIO.VERSIONS.forPage(pageAddr);
io.initRoot(pageAddr, rootId, pageMem.pageSize());
+ io.setInlineSize(pageAddr, 0);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MetadataStorage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MetadataStorage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MetadataStorage.java
index faf7608..47c3254 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MetadataStorage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/MetadataStorage.java
@@ -192,7 +192,7 @@ public class MetadataStorage implements MetaStore {
/** {@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(idx);
+ final int off = ((IndexIO)io).getOffset(pageAddr, idx);
int shift = 0;
@@ -214,7 +214,7 @@ public class MetadataStorage implements MetaStore {
/** {@inheritDoc} */
@Override protected IndexItem getRow(final BPlusIO<IndexItem> io, final long pageAddr,
final int idx) throws IgniteCheckedException {
- return readRow(pageAddr, ((IndexIO)io).getOffset(idx));
+ return readRow(pageAddr, ((IndexIO)io).getOffset(pageAddr, idx));
}
}
@@ -323,10 +323,11 @@ public class MetadataStorage implements MetaStore {
*/
private interface IndexIO {
/**
+ * @param pageAddr Page address.
* @param idx Index.
* @return Offset in buffer according to {@code idx}.
*/
- int getOffset(int idx);
+ int getOffset(long pageAddr, int idx);
}
/**
@@ -355,7 +356,7 @@ public class MetadataStorage implements MetaStore {
@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(srcIdx));
+ storeRow(dstPageAddr, offset(dstIdx), srcPageAddr, ((IndexIO)srcIo).getOffset(srcPageAddr, srcIdx));
}
/** {@inheritDoc} */
@@ -365,7 +366,7 @@ public class MetadataStorage implements MetaStore {
}
/** {@inheritDoc} */
- @Override public int getOffset(final int idx) {
+ @Override public int getOffset(long pageAddr, final int idx) {
return offset(idx);
}
}
@@ -398,7 +399,7 @@ public class MetadataStorage implements MetaStore {
final BPlusIO<IndexItem> srcIo,
final long srcPageAddr,
final int srcIdx) throws IgniteCheckedException {
- storeRow(dstPageAddr, offset(dstIdx), srcPageAddr, ((IndexIO)srcIo).getOffset(srcIdx));
+ storeRow(dstPageAddr, offset(dstIdx), srcPageAddr, ((IndexIO)srcIo).getOffset(srcPageAddr, srcIdx));
}
/** {@inheritDoc} */
@@ -409,7 +410,7 @@ public class MetadataStorage implements MetaStore {
}
/** {@inheritDoc} */
- @Override public int getOffset(final int idx) {
+ @Override public int getOffset(long pageAddr, final int idx) {
return offset(idx);
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
index 518d0d8..aa61fbd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
@@ -38,7 +38,7 @@ import org.apache.ignite.internal.pagemem.wal.record.delta.FixRemoveId;
import org.apache.ignite.internal.pagemem.wal.record.delta.InsertRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageAddRootRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageCutRootRecord;
-import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRootRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRootInlineRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.NewRootInitRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.RecycleRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.RemoveRecord;
@@ -103,16 +103,16 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
private final float maxFill;
/** */
- private final long metaPageId;
+ protected final long metaPageId;
/** */
- private final boolean canGetRowFromInner;
+ private boolean canGetRowFromInner;
/** */
- private final IOVersions<? extends BPlusInnerIO<L>> innerIos;
+ private IOVersions<? extends BPlusInnerIO<L>> innerIos;
/** */
- private final IOVersions<? extends BPlusLeafIO<L>> leafIos;
+ private IOVersions<? extends BPlusLeafIO<L>> leafIos;
/** */
private final AtomicLong globalRmvId;
@@ -661,7 +661,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
*/
private class InitRoot extends PageHandler<Long, Bool> {
/** {@inheritDoc} */
- @Override public Bool run(Page meta, PageIO iox, long pageAddr, Long rootId, int lvl)
+ @Override public Bool run(Page meta, PageIO iox, long pageAddr, Long rootId, int inlineSize)
throws IgniteCheckedException {
assert rootId != null;
@@ -669,9 +669,10 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
BPlusMetaIO io = (BPlusMetaIO)iox;
io.initRoot(pageAddr, rootId, pageSize());
+ io.setInlineSize(pageAddr, inlineSize);
if (needWalDeltaRecord(meta))
- wal.log(new MetaPageInitRootRecord(cacheId, meta.id(), rootId));
+ wal.log(new MetaPageInitRootInlineRecord(cacheId, meta.id(), rootId, inlineSize));
assert io.getRootLevel(pageAddr) == 0;
assert io.getFirstPageId(pageAddr, 0) == rootId;
@@ -694,7 +695,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
* @param leafIos Leaf IO versions.
* @throws IgniteCheckedException If failed.
*/
- public BPlusTree(
+ protected BPlusTree(
String name,
int cacheId,
PageMemory pageMem,
@@ -705,6 +706,29 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
IOVersions<? extends BPlusInnerIO<L>> innerIos,
IOVersions<? extends BPlusLeafIO<L>> leafIos
) throws IgniteCheckedException {
+ this(name, cacheId, pageMem, wal, globalRmvId, metaPageId, reuseList);
+ setIos(innerIos, leafIos);
+ }
+
+ /**
+ * @param name Tree name.
+ * @param cacheId Cache ID.
+ * @param pageMem Page memory.
+ * @param wal Write ahead log manager.
+ * @param globalRmvId Remove ID.
+ * @param metaPageId Meta page ID.
+ * @param reuseList Reuse list.
+ * @throws IgniteCheckedException If failed.
+ */
+ protected BPlusTree(
+ String name,
+ int cacheId,
+ PageMemory pageMem,
+ IgniteWriteAheadLogManager wal,
+ AtomicLong globalRmvId,
+ long metaPageId,
+ ReuseList reuseList
+ ) throws IgniteCheckedException {
super(cacheId, pageMem, wal);
assert !F.isEmpty(name);
@@ -713,13 +737,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
minFill = 0f; // Testing worst case when merge happens only on empty page.
maxFill = 0f; // Avoiding random effects on testing.
- assert innerIos != null;
- assert leafIos != null;
assert metaPageId != 0L;
- this.canGetRowFromInner = innerIos.latest().canGetRow(); // TODO refactor
- this.innerIos = innerIos;
- this.leafIos = leafIos;
this.metaPageId = metaPageId;
this.name = name;
this.reuseList = reuseList;
@@ -727,6 +746,20 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
}
/**
+ * @param innerIos Inner IO versions.
+ * @param leafIos Leaf IO versions.
+ */
+ protected void setIos(IOVersions<? extends BPlusInnerIO<L>> innerIos,
+ IOVersions<? extends BPlusLeafIO<L>> leafIos) {
+ assert innerIos != null;
+ assert leafIos != null;
+
+ this.canGetRowFromInner = innerIos.latest().canGetRow(); // TODO refactor
+ this.innerIos = innerIos;
+ this.leafIos = leafIos;
+ }
+
+ /**
* @return Tree name.
*/
public final String getName() {
@@ -748,6 +781,17 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
* @throws IgniteCheckedException If failed.
*/
protected final void initTree(boolean initNew) throws IgniteCheckedException {
+ initTree(initNew, 0);
+ }
+
+ /**
+ * Initialize new tree.
+ *
+ * @param initNew {@code True} if new tree should be created.
+ * @param inlineSize Inline size.
+ * @throws IgniteCheckedException If failed.
+ */
+ protected final void initTree(boolean initNew, int inlineSize) throws IgniteCheckedException {
if (initNew) {
// Allocate the first leaf page, it will be our root.
long rootId = allocatePage(null);
@@ -758,7 +802,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
// Initialize meta page with new root page.
try (Page meta = page(metaPageId)) {
- Bool res = writePage(pageMem, meta, this, initRoot, BPlusMetaIO.VERSIONS.latest(), wal, rootId, 0, FALSE);
+ Bool res = writePage(pageMem, meta, this, initRoot, BPlusMetaIO.VERSIONS.latest(), wal, rootId, inlineSize, FALSE);
assert res == TRUE: res;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIO.java
index 5186808..bcf2908 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIO.java
@@ -51,7 +51,6 @@ public abstract class BPlusIO<L> extends PageIO {
* @param ver Page format version.
* @param leaf If this is a leaf IO.
* @param canGetRow If we can get full row from this page.
- * @param itemSize Single item size on page.
*/
protected BPlusIO(int type, int ver, boolean leaf, boolean canGetRow, int itemSize) {
super(type, ver);
@@ -194,7 +193,7 @@ public abstract class BPlusIO<L> extends PageIO {
* @param idx Index of element.
* @return Offset from byte buffer begin in bytes.
*/
- protected abstract int offset(int idx);
+ public abstract int offset(int idx);
/**
* Store the needed info about the row in the page. Leaf and inner pages can store different info.
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusInnerIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusInnerIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusInnerIO.java
index b15c2dc..60fd24c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusInnerIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusInnerIO.java
@@ -49,7 +49,7 @@ public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
// The structure of the page is the following:
// |ITEMS_OFF|w|A|x|B|y|C|z|
// where capital letters are data items, lowercase letters are 8 byte page references.
- return (pageSize - ITEMS_OFF - 8) / (itemSize + 8);
+ return (pageSize - ITEMS_OFF - 8) / (getItemSize() + 8);
}
/**
@@ -58,7 +58,7 @@ public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
* @return Page ID.
*/
public final long getLeft(long pageAddr, int idx) {
- return PageUtils.getLong(pageAddr, (offset(idx, SHIFT_LEFT)));
+ return PageUtils.getLong(pageAddr, (offset0(idx, SHIFT_LEFT)));
}
/**
@@ -67,7 +67,7 @@ public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
* @param pageId Page ID.
*/
public final void setLeft(long pageAddr, int idx, long pageId) {
- PageUtils.putLong(pageAddr, offset(idx, SHIFT_LEFT), pageId);
+ PageUtils.putLong(pageAddr, offset0(idx, SHIFT_LEFT), pageId);
assert pageId == getLeft(pageAddr, idx);
}
@@ -78,7 +78,7 @@ public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
* @return Page ID.
*/
public final long getRight(long pageAddr, int idx) {
- return PageUtils.getLong(pageAddr, offset(idx, SHIFT_RIGHT));
+ return PageUtils.getLong(pageAddr, offset0(idx, SHIFT_RIGHT));
}
/**
@@ -87,7 +87,7 @@ public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
* @param pageId Page ID.
*/
private void setRight(long pageAddr, int idx, long pageId) {
- PageUtils.putLong(pageAddr, offset(idx, SHIFT_RIGHT), pageId);
+ PageUtils.putLong(pageAddr, offset0(idx, SHIFT_RIGHT), pageId);
assert pageId == getRight(pageAddr, idx);
}
@@ -97,17 +97,17 @@ public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
boolean cpLeft) throws IgniteCheckedException {
assert srcIdx != dstIdx || srcPageAddr != dstPageAddr;
- cnt *= itemSize + 8; // From items to bytes.
+ cnt *= getItemSize() + 8; // From items to bytes.
if (dstIdx > srcIdx) {
PageHandler.copyMemory(srcPageAddr, dstPageAddr, offset(srcIdx), offset(dstIdx), cnt);
if (cpLeft)
- PageUtils.putLong(dstPageAddr, offset(dstIdx, SHIFT_LEFT), PageUtils.getLong(srcPageAddr, (offset(srcIdx, SHIFT_LEFT))));
+ PageUtils.putLong(dstPageAddr, offset0(dstIdx, SHIFT_LEFT), PageUtils.getLong(srcPageAddr, (offset0(srcIdx, SHIFT_LEFT))));
}
else {
if (cpLeft)
- PageUtils.putLong(dstPageAddr, offset(dstIdx, SHIFT_LEFT), PageUtils.getLong(srcPageAddr, (offset(srcIdx, SHIFT_LEFT))));
+ PageUtils.putLong(dstPageAddr, offset0(dstIdx, SHIFT_LEFT), PageUtils.getLong(srcPageAddr, (offset0(srcIdx, SHIFT_LEFT))));
PageHandler.copyMemory(srcPageAddr, dstPageAddr, offset(srcIdx), offset(dstIdx), cnt);
}
@@ -118,13 +118,13 @@ public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
* @param shift It can be either link itself or left or right page ID.
* @return Offset from byte buffer begin in bytes.
*/
- private int offset(int idx, int shift) {
- return shift + (8 + itemSize) * idx;
+ private int offset0(int idx, int shift) {
+ return shift + (8 + getItemSize()) * idx;
}
/** {@inheritDoc} */
- @Override protected final int offset(int idx) {
- return offset(idx, SHIFT_LINK);
+ @Override public final int offset(int idx) {
+ return offset0(idx, SHIFT_LINK);
}
// Methods for B+Tree logic.
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusLeafIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusLeafIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusLeafIO.java
index f3dccee..f6011b3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusLeafIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusLeafIO.java
@@ -35,7 +35,7 @@ public abstract class BPlusLeafIO<L> extends BPlusIO<L> {
/** {@inheritDoc} */
@Override public int getMaxCount(long pageAddr, int pageSize) {
- return (pageSize - ITEMS_OFF) / itemSize;
+ return (pageSize - ITEMS_OFF) / getItemSize();
}
/** {@inheritDoc} */
@@ -43,13 +43,14 @@ public abstract class BPlusLeafIO<L> extends BPlusIO<L> {
boolean cpLeft) throws IgniteCheckedException {
assert srcIdx != dstIdx || srcPageAddr != dstPageAddr;
- PageHandler.copyMemory(srcPageAddr, dstPageAddr, offset(srcIdx), offset(dstIdx), cnt * itemSize);
+ PageHandler.copyMemory(srcPageAddr, dstPageAddr, offset(srcIdx), offset(dstIdx),
+ cnt * getItemSize());
}
/** {@inheritDoc} */
- @Override protected final int offset(int idx) {
+ @Override public final int offset(int idx) {
assert idx >= 0: idx;
- return ITEMS_OFF + idx * itemSize;
+ return ITEMS_OFF + idx * getItemSize();
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusMetaIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusMetaIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusMetaIO.java
index 8850863..6755820 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusMetaIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusMetaIO.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.processors.cache.database.tree.io;
+import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.pagemem.PageUtils;
/**
@@ -25,20 +26,38 @@ import org.apache.ignite.internal.pagemem.PageUtils;
public class BPlusMetaIO extends PageIO {
/** */
public static final IOVersions<BPlusMetaIO> VERSIONS = new IOVersions<>(
- new BPlusMetaIO(1)
+ new BPlusMetaIO(1), new BPlusMetaIO(2)
);
/** */
private static final int LVLS_OFF = COMMON_HEADER_END;
/** */
- private static final int REFS_OFF = LVLS_OFF + 1;
+ private final int refsOff;
+
+ /** */
+ private final int inlineSizeOff;
/**
* @param ver Page format version.
*/
private BPlusMetaIO(int ver) {
super(T_BPLUS_META, ver);
+
+ switch (ver) {
+ case 1:
+ inlineSizeOff = -1;
+ refsOff = LVLS_OFF + 1;
+ break;
+
+ case 2:
+ inlineSizeOff = LVLS_OFF + 1;
+ refsOff = inlineSizeOff + 2;
+ break;
+
+ default:
+ throw new IgniteException("invalid IO version: " + ver);
+ }
}
/**
@@ -65,7 +84,7 @@ public class BPlusMetaIO extends PageIO {
* @return Max levels possible for this page size.
*/
private int getMaxLevels(long pageAddr, int pageSize) {
- return (pageSize - REFS_OFF) / 8;
+ return (pageSize - refsOff) / 8;
}
/**
@@ -85,8 +104,8 @@ public class BPlusMetaIO extends PageIO {
* @param lvl Level.
* @return Offset for page reference.
*/
- private static int offset(int lvl) {
- return lvl * 8 + REFS_OFF;
+ private int offset(int lvl) {
+ return lvl * 8 + refsOff;
}
/**
@@ -144,4 +163,20 @@ public class BPlusMetaIO extends PageIO {
setLevelsCount(pageAddr, lvl, pageSize); // Decrease tree height.
}
+
+ /**
+ * @param pageAddr Page address.
+ * @param size Offset size.
+ */
+ public void setInlineSize(long pageAddr, int size) {
+ if (getVersion() > 1)
+ PageUtils.putShort(pageAddr, inlineSizeOff, (short)size);
+ }
+
+ /**
+ * @param pageAddr Page address.
+ */
+ public int getInlineSize(long pageAddr) {
+ return getVersion() > 1 ? PageUtils.getShort(pageAddr, inlineSizeOff) : 0;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
index 945f4dc..190349a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
@@ -452,10 +452,12 @@ public class DataPageIO extends PageIO {
}
/**
+ * Sets position to start of actual fragment data and limit to it's end.
+ *
* @param pageAddr Page address.
* @param itemId Item to position on.
* @param pageSize Page size.
- * @return Size and offset of actual fragment data, and link to the next fragment if data is fragmented.
+ * @return {@link DataPagePayload} object.
*/
public DataPagePayload readPayload(final long pageAddr, final int itemId, final int pageSize) {
int dataOff = getDataOffset(pageAddr, itemId, pageSize);
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPagePayload.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPagePayload.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPagePayload.java
index 7dedc00..277bdc7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPagePayload.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPagePayload.java
@@ -56,7 +56,7 @@ public class DataPagePayload {
}
/**
- * @return Next link.
+ * @return Link to the next fragment or {@code 0} if it is the last fragment or the data row is not fragmented.
*/
public long nextLink() {
return nextLink;
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
index f6ac905..6f50bf7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
@@ -18,6 +18,8 @@
package org.apache.ignite.internal.processors.cache.database.tree.io;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.pagemem.Page;
import org.apache.ignite.internal.pagemem.PageMemory;
@@ -76,6 +78,15 @@ public abstract class PageIO {
/** */
private static IOVersions<? extends BPlusLeafIO<?>> h2LeafIOs;
+ /** Maximum payload size. */
+ public static final short MAX_PAYLOAD_SIZE = 2048;
+
+ /** */
+ private static List<IOVersions<? extends BPlusInnerIO<?>>> h2ExtraInnerIOs = new ArrayList<>(MAX_PAYLOAD_SIZE);
+
+ /** */
+ private static List<IOVersions<? extends BPlusLeafIO<?>>> h2ExtraLeafIOs = new ArrayList<>(MAX_PAYLOAD_SIZE);
+
/** */
public static final int TYPE_OFF = 0;
@@ -147,6 +158,14 @@ public abstract class PageIO {
/** */
public static final short T_PAGE_UPDATE_TRACKING = 15;
+ /** Index for payload == 1. */
+ public static final short T_H2_EX_REF_LEAF_START = 10000;
+ public static final short T_H2_EX_REF_LEAF_END = T_H2_EX_REF_LEAF_START + MAX_PAYLOAD_SIZE - 1;
+
+ /** */
+ public static final short T_H2_EX_REF_INNER_START = 20000;
+ public static final short T_H2_EX_REF_INNER_END = T_H2_EX_REF_INNER_START + MAX_PAYLOAD_SIZE - 1;
+
/** */
private final int ver;
@@ -290,6 +309,40 @@ public abstract class PageIO {
}
/**
+ * Registers extra inner IO versions.
+ */
+ public static void registerH2ExtraInner(
+ IOVersions<? extends BPlusInnerIO<?>> innerExtIOs
+ ) {
+ h2ExtraInnerIOs.add(innerExtIOs);
+ }
+
+ /**
+ * Registers extra inner IO versions.
+ */
+ public static void registerH2ExtraLeaf(
+ IOVersions<? extends BPlusLeafIO<?>> leafExtIOs
+ ) {
+ h2ExtraLeafIOs.add(leafExtIOs);
+ }
+
+ /**
+ * @param idx Index.
+ * @return IOVersions for given idx.
+ */
+ public static IOVersions<? extends BPlusInnerIO<?>> getInnerVersions(int idx) {
+ return h2ExtraInnerIOs.get(idx);
+ }
+
+ /**
+ * @param idx Index.
+ * @return IOVersions for given idx.
+ */
+ public static IOVersions<? extends BPlusLeafIO<?>> getLeafVersions(int idx) {
+ return h2ExtraLeafIOs.get(idx);
+ }
+
+ /**
* Registers IOs for testing.
*
* @param innerIO Inner IO.
@@ -402,6 +455,13 @@ public abstract class PageIO {
*/
@SuppressWarnings("unchecked")
public static <Q extends BPlusIO<?>> Q getBPlusIO(int type, int ver) throws IgniteCheckedException {
+
+ if (type >= T_H2_EX_REF_LEAF_START && type <= T_H2_EX_REF_LEAF_END)
+ return (Q)h2ExtraLeafIOs.get(type - T_H2_EX_REF_LEAF_START).forVersion(ver);
+
+ if (type >= T_H2_EX_REF_INNER_START && type <= T_H2_EX_REF_INNER_END)
+ return (Q)h2ExtraInnerIOs.get(type - T_H2_EX_REF_INNER_START).forVersion(ver);
+
switch (type) {
case T_H2_REF_INNER:
if (h2InnerIOs == null)
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexDescriptor.java
index fe58112..bed2ffe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexDescriptor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexDescriptor.java
@@ -47,4 +47,11 @@ public interface GridQueryIndexDescriptor {
* @return Type.
*/
public GridQueryIndexType type();
+
+ /**
+ * Gets inline size for SORTED index.
+ *
+ * @return Inline size.
+ */
+ public int inlineSize();
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index cf85a52..03a6f9b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -17,12 +17,11 @@
package org.apache.ignite.internal.processors.query;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.concurrent.TimeUnit;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
@@ -40,6 +39,7 @@ import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
import javax.cache.Cache;
import javax.cache.CacheException;
import org.apache.ignite.IgniteCheckedException;
@@ -71,9 +71,9 @@ import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
-import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.cache.GridCacheDefaultAffinityKeyMapper;
import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
import org.apache.ignite.internal.processors.cache.query.CacheQueryFuture;
@@ -1700,7 +1700,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
idxName = QueryEntity.defaultIndexName(idx);
if (idx.getIndexType() == QueryIndexType.SORTED || idx.getIndexType() == QueryIndexType.GEOSPATIAL) {
- d.addIndex(idxName, idx.getIndexType() == QueryIndexType.SORTED ? SORTED : GEO_SPATIAL);
+ d.addIndex(idxName, idx.getIndexType() == QueryIndexType.SORTED ? SORTED : GEO_SPATIAL, idx.getInlineSize());
int i = 0;
@@ -2453,11 +2453,13 @@ public class GridQueryProcessor extends GridProcessorAdapter {
*
* @param idxName Index name.
* @param type Index type.
+ * @param inlineSize Inline size.
* @return Index descriptor.
* @throws IgniteCheckedException In case of error.
*/
- public IndexDescriptor addIndex(String idxName, GridQueryIndexType type) throws IgniteCheckedException {
- IndexDescriptor idx = new IndexDescriptor(type);
+ public IndexDescriptor addIndex(String idxName, GridQueryIndexType type,
+ int inlineSize) throws IgniteCheckedException {
+ IndexDescriptor idx = new IndexDescriptor(type, inlineSize);
if (indexes.put(idxName, idx) != null)
throw new IgniteCheckedException("Index with name '" + idxName + "' already exists.");
@@ -2466,6 +2468,18 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/**
+ * Adds index.
+ *
+ * @param idxName Index name.
+ * @param type Index type.
+ * @return Index descriptor.
+ * @throws IgniteCheckedException In case of error.
+ */
+ public IndexDescriptor addIndex(String idxName, GridQueryIndexType type) throws IgniteCheckedException {
+ return addIndex(idxName, type, 0);
+ }
+
+ /**
* Adds field to index.
*
* @param idxName Index name.
@@ -2653,13 +2667,25 @@ public class GridQueryProcessor extends GridProcessorAdapter {
/** */
private final GridQueryIndexType type;
+ /** */
+ private int inlineSize;
+
/**
* @param type Type.
+ * @param inlineSize Inline size.
*/
- private IndexDescriptor(GridQueryIndexType type) {
+ private IndexDescriptor(GridQueryIndexType type, int inlineSize) {
assert type != null;
this.type = type;
+ this.inlineSize = inlineSize;
+ }
+
+ /**
+ * @param type Type.
+ */
+ private IndexDescriptor(GridQueryIndexType type) {
+ this(type, 0);
}
/** {@inheritDoc} */
@@ -2701,6 +2727,11 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/** {@inheritDoc} */
+ @Override public int inlineSize() {
+ return inlineSize;
+ }
+
+ /** {@inheritDoc} */
@Override public String toString() {
return S.toString(IndexDescriptor.class, this);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 98b5b7f..b0e7956 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -85,8 +85,8 @@ import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
-import org.apache.ignite.internal.processors.query.GridQueryCancel;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.processors.query.GridQueryCancel;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
import org.apache.ignite.internal.processors.query.GridQueryFieldsResult;
import org.apache.ignite.internal.processors.query.GridQueryFieldsResultAdapter;
@@ -96,11 +96,13 @@ import org.apache.ignite.internal.processors.query.GridQueryProperty;
import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.processors.query.h2.database.H2PkHashIndex;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2DefaultTableEngine;
import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory;
import org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex;
+import org.apache.ignite.internal.processors.query.h2.database.io.H2ExtrasInnerIO;
+import org.apache.ignite.internal.processors.query.h2.database.io.H2ExtrasLeafIO;
import org.apache.ignite.internal.processors.query.h2.database.io.H2InnerIO;
import org.apache.ignite.internal.processors.query.h2.database.io.H2LeafIO;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2DefaultTableEngine;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOffheap;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext;
@@ -209,13 +211,16 @@ import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType
*/
@SuppressWarnings({"UnnecessaryFullyQualifiedName", "NonFinalStaticVariableUsedInClassInitialization"})
public class IgniteH2Indexing implements GridQueryIndexing {
+
/**
* Register IO for indexes.
*/
static {
PageIO.registerH2(H2InnerIO.VERSIONS, H2LeafIO.VERSIONS);
+ H2ExtrasInnerIO.register();
+ H2ExtrasLeafIO.register();
}
-
+
/** Default DB options. */
private static final String DB_OPTIONS = ";LOCK_MODE=3;MULTI_THREADED=1;DB_CLOSE_ON_EXIT=FALSE" +
";DEFAULT_LOCK_TIMEOUT=10000;FUNCTIONS_IN_SCHEMA=true;OPTIMIZE_REUSE_RESULTS=0;QUERY_CACHE_SIZE=0" +
@@ -2596,7 +2601,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
"_key_PK",
tbl,
true,
- treeIndexColumns(new ArrayList<IndexColumn>(2), keyCol, affCol)));
+ treeIndexColumns(new ArrayList<IndexColumn>(2), keyCol, affCol),
+ -1));
if (type().valueClass() == String.class) {
try {
@@ -2641,7 +2647,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
cols = treeIndexColumns(cols, keyCol, affCol);
- idxs.add(createSortedIndex(cacheId, name, tbl, false, cols));
+ idxs.add(createSortedIndex(cacheId, name, tbl, false, cols, idx.inlineSize()));
}
else if (idx.type() == GEO_SPATIAL)
idxs.add(createH2SpatialIndex(tbl, name, cols.toArray(new IndexColumn[cols.size()])));
@@ -2653,7 +2659,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
// Add explicit affinity key index if nothing alike was found.
if (affCol != null && !affIdxFound) {
idxs.add(createSortedIndex(cacheId, "AFFINITY_KEY", tbl, false,
- treeIndexColumns(new ArrayList<IndexColumn>(2), affCol, keyCol)));
+ treeIndexColumns(new ArrayList<IndexColumn>(2), affCol, keyCol), -1));
}
return idxs;
@@ -2672,7 +2678,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
String name,
GridH2Table tbl,
boolean pk,
- List<IndexColumn> cols
+ List<IndexColumn> cols,
+ int inlineSize
) {
try {
GridCacheSharedContext<Object, Object> scctx = ctx.cache().context();
@@ -2682,7 +2689,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
if (log.isInfoEnabled())
log.info("Creating cache index [cacheId=" + cctx.cacheId() + ", idxName=" + name + ']');
- return new H2TreeIndex(cctx, tbl, name, pk, cols);
+ return new H2TreeIndex(cctx, tbl, name, pk, cols, inlineSize);
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
index 19e05ed..dd37492 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
@@ -19,14 +19,17 @@ package org.apache.ignite.internal.processors.query.h2.database;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.Page;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree;
import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO;
+import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusMetaIO;
import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList;
-import org.apache.ignite.internal.processors.query.h2.database.io.H2InnerIO;
-import org.apache.ignite.internal.processors.query.h2.database.io.H2LeafIO;
+import org.apache.ignite.internal.processors.query.h2.database.io.H2ExtrasInnerIO;
+import org.apache.ignite.internal.processors.query.h2.database.io.H2ExtrasLeafIO;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.h2.result.SearchRow;
/**
@@ -35,6 +38,9 @@ public abstract class H2Tree extends BPlusTree<SearchRow, GridH2Row> {
/** */
private final H2RowFactory rowStore;
+ /** */
+ private final int inlineSize;
+
/**
* @param name Tree name.
* @param reuseList Reuse list.
@@ -46,7 +52,7 @@ public abstract class H2Tree extends BPlusTree<SearchRow, GridH2Row> {
* @param initNew Initialize new index.
* @throws IgniteCheckedException If failed.
*/
- public H2Tree(
+ protected H2Tree(
String name,
ReuseList reuseList,
int cacheId,
@@ -55,15 +61,25 @@ public abstract class H2Tree extends BPlusTree<SearchRow, GridH2Row> {
AtomicLong globalRmvId,
H2RowFactory rowStore,
long metaPageId,
- boolean initNew
+ boolean initNew,
+ int inlineSize
) throws IgniteCheckedException {
- super(name, cacheId, pageMem, wal, globalRmvId, metaPageId, reuseList, H2InnerIO.VERSIONS, H2LeafIO.VERSIONS);
+ super(name, cacheId, pageMem, wal, globalRmvId, metaPageId, reuseList);
+
+ if (!initNew) {
+ // Page is ready - read inline size from it.
+ inlineSize = getMetaInlineSize();
+ }
+
+ this.inlineSize = inlineSize;
assert rowStore != null;
this.rowStore = rowStore;
- initTree(initNew);
+ setIos(H2ExtrasInnerIO.getVersions(inlineSize), H2ExtrasLeafIO.getVersions(inlineSize));
+
+ initTree(initNew, inlineSize);
}
/**
@@ -78,6 +94,35 @@ public abstract class H2Tree extends BPlusTree<SearchRow, GridH2Row> {
throws IgniteCheckedException {
return (GridH2Row)io.getLookupRow(this, pageAddr, idx);
}
+
+ /**
+ * @return Inline size.
+ */
+ public int inlineSize() {
+ return inlineSize;
+ }
+
+ /**
+ * @return Inline size.
+ * @throws IgniteCheckedException
+ */
+ private int getMetaInlineSize() throws IgniteCheckedException {
+ try (Page meta = page(metaPageId)) {
+ long pageAddr = readLock(meta); // Meta can't be removed.
+
+ assert pageAddr != 0 : "Failed to read lock meta page [page=" + meta + ", metaPageId=" +
+ U.hexLong(metaPageId) + ']';
+
+ try {
+ BPlusMetaIO io = BPlusMetaIO.VERSIONS.forPage(pageAddr);
+
+ return io.getInlineSize(pageAddr);
+ }
+ finally {
+ readUnlock(meta, pageAddr);
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
index 9bcdab5..be5be0a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
@@ -17,18 +17,24 @@
package org.apache.ignite.internal.processors.query.h2.database;
+import java.util.ArrayList;
import java.util.List;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.database.IgniteCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.cache.database.RootPage;
import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree;
import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO;
-import org.apache.ignite.internal.processors.query.h2.*;
-import org.apache.ignite.internal.processors.query.h2.opt.*;
-import org.apache.ignite.internal.util.*;
-import org.apache.ignite.internal.util.lang.*;
+import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
+import org.apache.ignite.internal.processors.query.h2.H2Cursor;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
+import org.apache.ignite.internal.util.IgniteTree;
+import org.apache.ignite.internal.util.lang.GridCursor;
+import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.spi.indexing.IndexingQueryFilter;
import org.h2.engine.Session;
@@ -39,15 +45,25 @@ import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.IndexColumn;
import org.h2.table.TableFilter;
+import org.h2.value.Value;
import org.jetbrains.annotations.Nullable;
/**
* H2 Index over {@link BPlusTree}.
*/
public class H2TreeIndex extends GridH2IndexBase {
+ /** Default value for {@code IGNITE_MAX_INDEX_PAYLOAD_SIZE} */
+ public static final int IGNITE_MAX_INDEX_PAYLOAD_SIZE_DEFAULT = 0;
+
+ /** PageContext for use in IO's */
+ private static final ThreadLocal<H2TreeIndex> currentIndex = new ThreadLocal<>();
+
/** */
private final H2Tree tree;
+ /** */
+ private final List<InlineIndexHelper> inlineIdxs;
+
/** Cache context. */
private GridCacheContext<?, ?> cctx;
@@ -57,14 +73,16 @@ public class H2TreeIndex extends GridH2IndexBase {
* @param name Index name.
* @param pk Primary key.
* @param colsList Index columns.
+ * @param inlineSize Inline size.
* @throws IgniteCheckedException If failed.
*/
public H2TreeIndex(
- GridCacheContext<?,?> cctx,
+ GridCacheContext<?, ?> cctx,
GridH2Table tbl,
String name,
boolean pk,
- List<IndexColumn> colsList
+ List<IndexColumn> colsList,
+ int inlineSize
) throws IgniteCheckedException {
this.cctx = cctx;
IndexColumn[] cols = colsList.toArray(new IndexColumn[colsList.size()]);
@@ -83,34 +101,151 @@ public class H2TreeIndex extends GridH2IndexBase {
RootPage page = cctx.offheap().rootPageForIndex(name);
+ inlineIdxs = getAvailableInlineColumns(cols);
+
tree = new H2Tree(name, cctx.offheap().reuseListForIndex(name), cctx.cacheId(),
dbMgr.pageMemory(), cctx.shared().wal(), cctx.offheap().globalRemoveId(),
- tbl.rowFactory(), page.pageId().pageId(), page.isAllocated()) {
+ tbl.rowFactory(), page.pageId().pageId(), page.isAllocated(), computeInlineSize(inlineIdxs, inlineSize)) {
@Override protected int compare(BPlusIO<SearchRow> io, long pageAddr, int idx, SearchRow row)
throws IgniteCheckedException {
- return compareRows(getRow(io, pageAddr, idx), row);
+
+ if (inlineSize() == 0)
+ return compareRows(getRow(io, pageAddr, idx), row);
+ else {
+ int off = io.offset(idx);
+
+ int fieldOff = 0;
+
+ int lastIdxUsed = 0;
+
+ for (int i = 0; i < inlineIdxs.size(); i++) {
+ InlineIndexHelper inlineIdx = inlineIdxs.get(i);
+
+ Value v2 = row.getValue(inlineIdx.columnIndex());
+
+ if (v2 == null)
+ return 0;
+
+ Value v1 = inlineIdx.get(pageAddr, off + fieldOff, inlineSize() - fieldOff);
+
+ if (v1 == null)
+ break;
+
+ int c = compareValues(v1, v2, inlineIdx.sortType());
+
+ if (!canRelyOnCompare(c, v1, v2, inlineIdx))
+ break;
+
+ lastIdxUsed++;
+
+ if (c != 0)
+ return c;
+
+ fieldOff += inlineIdx.fullSize(pageAddr, off + fieldOff);
+
+ if (fieldOff > inlineSize())
+ break;
+ }
+
+ SearchRow rowData = getRow(io, pageAddr, idx);
+
+ for (int i = lastIdxUsed, len = indexColumns.length; i < len; i++) {
+ int idx0 = columnIds[i];
+
+ Value v2 = row.getValue(idx0);
+ if (v2 == null) {
+ // Can't compare further.
+ return 0;
+ }
+
+ Value v1 = rowData.getValue(idx0);
+
+ int c = compareValues(v1, v2, indexColumns[i].sortType);
+ if (c != 0)
+ return c;
+ }
+
+ return 0;
+ }
}
};
}
- else
+ else {
// We need indexes on the client node, but index will not contain any data.
tree = null;
+ inlineIdxs = null;
+ }
initDistributedJoinMessaging(tbl);
}
/**
+ * @param cols Columns array.
+ * @return List of {@link InlineIndexHelper} objects.
+ */
+ private List<InlineIndexHelper> getAvailableInlineColumns(IndexColumn[] cols) {
+
+ // todo: null
+ List<InlineIndexHelper> res = new ArrayList<>();
+
+ for (int i = 0; i < cols.length; i++) {
+ IndexColumn col = cols[i];
+
+ if (!InlineIndexHelper.AVAILABLE_TYPES.contains(col.column.getType()))
+ break;
+
+ InlineIndexHelper idx = new InlineIndexHelper(col.column.getType(), col.column.getColumnId(), col.sortType);
+
+ res.add(idx);
+ }
+
+ return res;
+ }
+
+ /**
+ * @return Tree updated in current thread.
+ */
+ public static H2TreeIndex getCurrentIndex() {
+ return currentIndex.get();
+ }
+
+ /**
+ * @param a First value.
+ * @param b Second Value.
+ * @param sortType Sort type.
+ * @return Compare result.
+ */
+ private int compareValues(Value a, Value b, int sortType) {
+ if (a == b)
+ return 0;
+
+ int comp = table.compareTypeSafe(a, b);
+
+ if ((sortType & SortOrder.DESCENDING) != 0)
+ comp = -comp;
+
+ return comp;
+ }
+
+ /**
* @return Tree.
*/
public H2Tree tree() {
return tree;
}
+ /**
+ * @return InlineIndexHelper list.
+ */
+ public List<InlineIndexHelper> inlineIndexes() {
+ return inlineIdxs;
+ }
+
/** {@inheritDoc} */
@Override public Cursor find(Session ses, SearchRow lower, SearchRow upper) {
try {
IndexingQueryFilter f = threadLocalFilter();
- IgniteBiPredicate<Object,Object> p = null;
+ IgniteBiPredicate<Object, Object> p = null;
if (f != null) {
String spaceName = getTable().spaceName();
@@ -138,41 +273,59 @@ public class H2TreeIndex extends GridH2IndexBase {
/** {@inheritDoc} */
@Override public GridH2Row put(GridH2Row row) {
try {
+ currentIndex.set(this);
+
return tree.put(row);
}
catch (IgniteCheckedException e) {
throw DbException.convert(e);
}
+ finally {
+ currentIndex.remove();
+ }
}
/** {@inheritDoc} */
@Override public boolean putx(GridH2Row row) {
try {
+ currentIndex.set(this);
+
return tree.putx(row);
}
catch (IgniteCheckedException e) {
throw DbException.convert(e);
}
+ finally {
+ currentIndex.remove();
+ }
}
/** {@inheritDoc} */
@Override public GridH2Row remove(SearchRow row) {
try {
+ currentIndex.set(this);
return tree.remove(row);
}
catch (IgniteCheckedException e) {
throw DbException.convert(e);
}
+ finally {
+ currentIndex.remove();
+ }
}
/** {@inheritDoc} */
@Override public void removex(SearchRow row) {
try {
+ currentIndex.set(this);
tree.removex(row);
}
catch (IgniteCheckedException e) {
throw DbException.convert(e);
}
+ finally {
+ currentIndex.remove();
+ }
}
/** {@inheritDoc} */
@@ -262,4 +415,67 @@ public class H2TreeIndex extends GridH2IndexBase {
throw DbException.convert(e);
}
}
+
+ /**
+ * @param inlineIdxs Inline index helpers.
+ * @param cfgInlineSize Inline size from cache config.
+ * @return Inline size.
+ */
+ private int computeInlineSize(List<InlineIndexHelper> inlineIdxs, int cfgInlineSize) {
+ int maxSize = PageIO.MAX_PAYLOAD_SIZE;
+
+ int propSize = IgniteSystemProperties.getInteger(IgniteSystemProperties.IGNITE_MAX_INDEX_PAYLOAD_SIZE,
+ IGNITE_MAX_INDEX_PAYLOAD_SIZE_DEFAULT);
+
+ if (cfgInlineSize == 0)
+ return 0;
+
+ if (F.isEmpty(inlineIdxs))
+ return 0;
+
+ if (cfgInlineSize == -1) {
+ if (propSize == 0)
+ return 0;
+
+ int size = 0;
+
+ for (int i = 0; i < inlineIdxs.size(); i++) {
+ InlineIndexHelper idxHelper = inlineIdxs.get(i);
+ if (idxHelper.size() <= 0) {
+ size = propSize;
+ break;
+ }
+ // 1 byte type + size
+ size += idxHelper.size() + 1;
+ }
+
+ return Math.min(maxSize, size);
+ }
+ else
+ return Math.min(maxSize, cfgInlineSize);
+ }
+
+ /**
+ * @param c Compare result.
+ * @param shortVal Short value.
+ * @param v2 Second value;
+ * @param inlineIdx Index helper.
+ * @return {@code true} if we can rely on compare result.
+ */
+ protected static boolean canRelyOnCompare(int c, Value shortVal, Value v2, InlineIndexHelper inlineIdx) {
+ if (inlineIdx.type() == Value.STRING) {
+ if (c == 0 && shortVal.getType() != Value.NULL && v2.getType() != Value.NULL)
+ return false;
+
+ if (shortVal.getType() != Value.NULL
+ && v2.getType() != Value.NULL
+ && ((c < 0 && inlineIdx.sortType() == SortOrder.ASCENDING) || (c > 0 && inlineIdx.sortType() == SortOrder.DESCENDING))
+ && shortVal.getString().length() <= v2.getString().length()) {
+ // Can't rely on compare, should use full string.
+ return false;
+ }
+ }
+
+ return true;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java
new file mode 100644
index 0000000..ff44df5
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.h2.database;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.ignite.internal.pagemem.PageUtils;
+import org.h2.table.IndexColumn;
+import org.h2.value.Value;
+import org.h2.value.ValueBoolean;
+import org.h2.value.ValueByte;
+import org.h2.value.ValueInt;
+import org.h2.value.ValueLong;
+import org.h2.value.ValueNull;
+import org.h2.value.ValueString;
+
+/**
+ * Helper class for in-page indexes.
+ */
+public class InlineIndexHelper {
+ private static final Charset CHARSET = StandardCharsets.UTF_8;
+
+ /** */
+ public static final List<Integer> AVAILABLE_TYPES = Arrays.asList(
+ Value.BOOLEAN,
+ Value.BYTE,
+ Value.SHORT,
+ Value.INT,
+ Value.LONG,
+ Value.STRING
+ );
+
+ /** */
+ private final int type;
+
+ /** */
+ private final int colIdx;
+
+ /** */
+ private final int sortType;
+
+ /**
+ * @param type Index type (see {@link Value}).
+ * @param colIdx Index column index.
+ * @param sortType Column sort type (see {@link IndexColumn#sortType}).
+ */
+ public InlineIndexHelper(int type, int colIdx, int sortType) {
+ this.type = type;
+ this.colIdx = colIdx;
+ this.sortType = sortType;
+ }
+
+ /**
+ * @return Index type.
+ */
+ public int type() {
+ return type;
+ }
+
+ /**
+ * @return Column index.
+ */
+ public int columnIndex() {
+ return colIdx;
+ }
+
+ /**
+ * @return Sort type.
+ */
+ public int sortType() {
+ return sortType;
+ }
+
+ /**
+ * @return Value size.
+ */
+ public short size() {
+ switch (type) {
+ case Value.BOOLEAN:
+ case Value.BYTE:
+ return 1;
+
+ case Value.SHORT:
+ return 2;
+
+ case Value.INT:
+ return 4;
+
+ case Value.LONG:
+ return 8;
+
+ case Value.STRING:
+ return -1;
+
+ default:
+ throw new UnsupportedOperationException("no get operation for fast index type " + type);
+ }
+ }
+
+ /**
+ * @param pageAddr Page address.
+ * @param off Offset.
+ * @return Full size in page.
+ */
+ public int fullSize(long pageAddr, int off) {
+ int type = PageUtils.getByte(pageAddr, off);
+
+ if (type == Value.NULL)
+ return 1;
+
+ switch (type) {
+ case Value.BOOLEAN:
+ case Value.BYTE:
+ case Value.INT:
+ case Value.SHORT:
+ case Value.LONG:
+ return size() + 1;
+
+ case Value.STRING:
+ return PageUtils.getShort(pageAddr, off + 1) + 3;
+
+ default:
+ throw new UnsupportedOperationException("no get operation for fast index type " + type);
+ }
+ }
+
+ /**
+ * @param pageAddr Page address.
+ * @param off Offset.
+ * @return Value.
+ */
+ public Value get(long pageAddr, int off, int maxSize) {
+ if (size() > 0 && size() + 1 > maxSize)
+ return null;
+
+ int type = PageUtils.getByte(pageAddr, off);
+
+ if (type == Value.UNKNOWN)
+ return null;
+
+ if (type == Value.NULL)
+ return ValueNull.INSTANCE;
+
+ if (this.type != type)
+ throw new UnsupportedOperationException("invalid fast index type " + type);
+
+ switch (this.type) {
+ case Value.BOOLEAN:
+ return ValueBoolean.get(PageUtils.getByte(pageAddr, off + 1) != 0);
+
+ case Value.BYTE:
+ return ValueByte.get(PageUtils.getByte(pageAddr, off + 1));
+
+ case Value.SHORT:
+ return ValueInt.get(PageUtils.getShort(pageAddr, off + 1));
+
+ case Value.INT:
+ return ValueInt.get(PageUtils.getInt(pageAddr, off + 1));
+
+ case Value.LONG:
+ return ValueLong.get(PageUtils.getLong(pageAddr, off + 1));
+
+ case Value.STRING:
+ short size = PageUtils.getShort(pageAddr, off + 1);
+ return ValueString.get(new String(PageUtils.getBytes(pageAddr, off + 3, size), CHARSET));
+
+ default:
+ throw new UnsupportedOperationException("no get operation for fast index type " + type);
+ }
+ }
+
+ /**
+ * @param pageAddr Page address.
+ * @param off Offset.
+ * @param val Value.
+ * @return NUmber of bytes saved.
+ */
+ public int put(long pageAddr, int off, Value val, int maxSize) {
+ if (size() > 0 && size() + 1 > maxSize)
+ return 0;
+
+ if (val.getType() == Value.NULL) {
+ PageUtils.putByte(pageAddr, off, (byte)Value.NULL);
+ return 1;
+ }
+
+ if (val.getType() != type)
+ throw new UnsupportedOperationException("value type doesn't match");
+
+ switch (type) {
+ case Value.BOOLEAN:
+ PageUtils.putByte(pageAddr, off, (byte)val.getType());
+ PageUtils.putByte(pageAddr, off + 1, (byte)(val.getBoolean() ? 1 : 0));
+ return size() + 1;
+
+ case Value.BYTE:
+ PageUtils.putByte(pageAddr, off, (byte)val.getType());
+ PageUtils.putByte(pageAddr, off + 1, val.getByte());
+ return size() + 1;
+
+ case Value.SHORT:
+ PageUtils.putByte(pageAddr, off, (byte)val.getType());
+ PageUtils.putShort(pageAddr, off + 1, val.getShort());
+ return size() + 1;
+
+ case Value.INT:
+ PageUtils.putByte(pageAddr, off, (byte)val.getType());
+ PageUtils.putInt(pageAddr, off + 1, val.getInt());
+ return size() + 1;
+
+ case Value.LONG:
+ PageUtils.putByte(pageAddr, off, (byte)val.getType());
+ PageUtils.putLong(pageAddr, off + 1, val.getLong());
+ return size() + 1;
+
+ case Value.STRING:
+ byte[] s;
+ if (val.getString().getBytes(CHARSET).length + 3 <= maxSize)
+ s = val.getString().getBytes(CHARSET);
+ else
+ s = toBytes(val.getString(), maxSize - 3);
+
+ if (s == null) {
+ // Can't fit anything to
+ PageUtils.putByte(pageAddr, off, (byte)Value.UNKNOWN);
+ return 0;
+ }
+ else {
+ PageUtils.putByte(pageAddr, off, (byte)val.getType());
+ PageUtils.putShort(pageAddr, off + 1, (short)s.length);
+ PageUtils.putBytes(pageAddr, off + 3, s);
+ return s.length + 3;
+ }
+
+ default:
+ throw new UnsupportedOperationException("no get operation for fast index type " + type);
+ }
+ }
+
+ /**
+ * Convert String to byte[] with size limit, according to UTF-8 encoding.
+ *
+ * @param s String.
+ * @param limit Size limit.
+ * @return byte[].
+ */
+ public static byte[] toBytes(String s, int limit) {
+ byte[] bytes = s.getBytes(CHARSET);
+ if (bytes.length <= limit)
+ return bytes;
+
+ for (int i = bytes.length - 1; i > 0; i--) {
+ if ((bytes[i] & 0xc0) != 0x80 && i <= limit) {
+ byte[] res = new byte[i];
+ System.arraycopy(bytes, 0, res, 0, i);
+ return res;
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8f836cb0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/io/H2ExtrasInnerIO.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/io/H2ExtrasInnerIO.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/io/H2ExtrasInnerIO.java
new file mode 100644
index 0000000..5a8a681
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/io/H2ExtrasInnerIO.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.h2.database.io;
+
+import java.util.List;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.PageUtils;
+import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree;
+import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO;
+import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusInnerIO;
+import org.apache.ignite.internal.processors.cache.database.tree.io.IOVersions;
+import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
+import org.apache.ignite.internal.processors.query.h2.database.H2Tree;
+import org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex;
+import org.apache.ignite.internal.processors.query.h2.database.InlineIndexHelper;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
+import org.h2.result.SearchRow;
+
+/**
+ * Inner page for H2 row references.
+ */
+public class H2ExtrasInnerIO extends BPlusInnerIO<SearchRow> {
+ /** Payload size. */
+ private final int payloadSize;
+
+ /** */
+ public static void register() {
+ for (short payload = 1; payload <= PageIO.MAX_PAYLOAD_SIZE; payload++)
+ PageIO.registerH2ExtraInner(getVersions((short)(PageIO.T_H2_EX_REF_INNER_START + payload - 1), payload));
+ }
+
+ /**
+ * @param payload Payload size.
+ * @return IOVersions for given payload.
+ */
+ public static IOVersions<? extends BPlusInnerIO<SearchRow>> getVersions(int payload) {
+ assert payload >= 0 && payload <= PageIO.MAX_PAYLOAD_SIZE;
+
+ if (payload == 0)
+ return H2InnerIO.VERSIONS;
+ else
+ return (IOVersions<BPlusInnerIO<SearchRow>>)PageIO.getInnerVersions((short)(payload - 1));
+ }
+
+ /** */
+ private static IOVersions<H2ExtrasInnerIO> getVersions(short type, short payload) {
+ return new IOVersions<>(new H2ExtrasInnerIO(type, 1, payload));
+ }
+
+ /**
+ * @param type Page type.
+ * @param ver Page format version.
+ * @param payloadSize Payload size.
+ */
+ private H2ExtrasInnerIO(short type, int ver, int payloadSize) {
+ super(type, ver, true, 8 + payloadSize);
+ this.payloadSize = payloadSize;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void storeByOffset(long pageAddr, int off, SearchRow row) {
+ GridH2Row row0 = (GridH2Row)row;
+
+ assert row0.link != 0 : row0;
+
+ H2TreeIndex currentIdx = H2TreeIndex.getCurrentIndex();
+ assert currentIdx != null;
+ List<InlineIndexHelper> inlineIdx = currentIdx.inlineIndexes();
+
+ assert inlineIdx != null;
+
+ int fieldOff = 0;
+
+ for (int i = 0; i < inlineIdx.size(); i++) {
+ InlineIndexHelper idx = inlineIdx.get(i);
+ int size = idx.put(pageAddr, off + fieldOff, row.getValue(idx.columnIndex()), payloadSize - fieldOff);
+ if (size == 0)
+ break;
+ fieldOff += size;
+ }
+
+ PageUtils.putLong(pageAddr, off + payloadSize, row0.link);
+ }
+
+ /** {@inheritDoc} */
+ @Override public SearchRow getLookupRow(BPlusTree<SearchRow, ?> tree, long pageAddr, int idx)
+ throws IgniteCheckedException {
+ long link = getLink(pageAddr, idx);
+
+ assert link != 0;
+
+ GridH2Row r0 = ((H2Tree)tree).getRowFactory().getRow(link);
+
+ return r0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void store(long dstPageAddr, int dstIdx, BPlusIO<SearchRow> srcIo, long srcPageAddr, int srcIdx) {
+ int srcOff = srcIo.offset(srcIdx);
+
+ byte[] payload = PageUtils.getBytes(srcPageAddr, srcOff, payloadSize);
+ long link = PageUtils.getLong(srcPageAddr, srcOff + payloadSize);
+
+ assert link != 0;
+
+ int dstOff = offset(dstIdx);
+
+ PageUtils.putBytes(dstPageAddr, dstOff, payload);
+ PageUtils.putLong(dstPageAddr, dstOff + payloadSize, link);
+ }
+
+ /**
+ * @param pageAddr Page address.
+ * @param idx Index.
+ * @return Link to row.
+ */
+ private long getLink(long pageAddr, int idx) {
+ return PageUtils.getLong(pageAddr, offset(idx) + payloadSize);
+ }
+}