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 2014/12/10 16:59:10 UTC
[01/17] incubator-ignite git commit: ignite-qry - merged
Repository: incubator-ignite
Updated Branches:
refs/heads/master 7f6fdca44 -> 7b13de917
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/GridIndexingSpiAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/GridIndexingSpiAbstractSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/GridIndexingSpiAbstractSelfTest.java
deleted file mode 100644
index bd647f5..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/GridIndexingSpiAbstractSelfTest.java
+++ /dev/null
@@ -1,594 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing;
-
-import org.apache.ignite.*;
-import org.apache.ignite.marshaller.*;
-import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.indexing.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.spi.indexing.h2.*;
-import org.gridgain.grid.util.typedef.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.testframework.*;
-import org.gridgain.testframework.junits.spi.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-/**
- * Tests for all SQL based indexing SPI implementations.
- */
-public abstract class GridIndexingSpiAbstractSelfTest<X extends IndexingSpi>
- extends GridSpiAbstractTest<X> {
- /** */
- private static final TextIndex textIdx = new TextIndex(F.asList("txt"));
-
- /** */
- private static final Map<String, Class<?>> fieldsAA = new HashMap<>();
-
- /** */
- private static final Map<String, Class<?>> fieldsAB = new HashMap<>();
-
- /** */
- private static final Map<String, Class<?>> fieldsBA = new HashMap<>();
-
- /**
- * Fields initialization.
- */
- static {
- fieldsAA.put("id", Long.class);
- fieldsAA.put("name", String.class);
- fieldsAA.put("age", Integer.class);
-
- fieldsAB.putAll(fieldsAA);
- fieldsAB.put("txt", String.class);
-
- fieldsBA.putAll(fieldsAA);
- fieldsBA.put("sex", Boolean.class);
- }
-
- /** */
- private static TypeDesc typeAA = new TypeDesc("A", "A", fieldsAA, null);
-
- /** */
- private static TypeDesc typeAB = new TypeDesc("A", "B", fieldsAB, textIdx);
-
- /** */
- private static TypeDesc typeBA = new TypeDesc("B", "A", fieldsBA, null);
-
- /** {@inheritDoc} */
- @Override protected void spiConfigure(X spi) throws Exception {
- super.spiConfigure(spi);
-
- spi.registerMarshaller(new IdxMarshaller(getTestResources().getMarshaller()));
-
- spi.registerSpace("A");
- spi.registerSpace("B");
- }
-
- /**
- * @param id Id.
- * @param name Name.
- * @param age Age.
- * @return AA.
- */
- private Map<String, Object> aa(long id, String name, int age) {
- Map<String, Object> map = new HashMap<>();
-
- map.put("id", id);
- map.put("name", name);
- map.put("age", age);
-
- return map;
- }
-
- /**
- * @param id Id.
- * @param name Name.
- * @param age Age.
- * @param txt Text.
- * @return AB.
- */
- private Map<String, Object> ab(long id, String name, int age, String txt) {
- Map<String, Object> map = aa(id, name, age);
-
- map.put("txt", txt);
-
- return map;
- }
-
- /**
- * @param id Id.
- * @param name Name.
- * @param age Age.
- * @param sex Sex.
- * @return BA.
- */
- private Map<String, Object> ba(long id, String name, int age, boolean sex) {
- Map<String, Object> map = aa(id, name, age);
-
- map.put("sex", sex);
-
- return map;
- }
-
- /**
- * @param val Value.
- * @param <T> Value type.
- * @return Indexing entity.
- * @throws GridException If failed.
- */
- private <T> IndexingEntity<T> entity(T val) throws GridException {
- return new IndexingEntityAdapter<>(val, getTestResources().getMarshaller().marshal(val));
- }
-
- /**
- * @param row Row
- * @return Value.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private Map<String, Object> value(IndexingKeyValueRow<Integer, Map<String, Object>> row) throws IgniteSpiException {
- return row.value().value();
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testSpi() throws Exception {
- X spi = getSpi();
-
- assertEquals(-1, spi.size(typeAA.space(), typeAA));
- assertEquals(-1, spi.size(typeAB.space(), typeAB));
- assertEquals(-1, spi.size(typeBA.space(), typeBA));
-
- spi.registerType(typeAA.space(), typeAA);
-
- assertEquals(0, spi.size(typeAA.space(), typeAA));
- assertEquals(-1, spi.size(typeAB.space(), typeAB));
- assertEquals(-1, spi.size(typeBA.space(), typeBA));
-
- spi.registerType(typeAB.space(), typeAB);
-
- assertEquals(0, spi.size(typeAA.space(), typeAA));
- assertEquals(0, spi.size(typeAB.space(), typeAB));
- assertEquals(-1, spi.size(typeBA.space(), typeBA));
-
- spi.registerType(typeBA.space(), typeBA);
-
- // Initially all is empty.
- assertEquals(0, spi.size(typeAA.space(), typeAA));
- assertEquals(0, spi.size(typeAB.space(), typeAB));
- assertEquals(0, spi.size(typeBA.space(), typeBA));
-
- assertFalse(spi.query(typeAA.space(), "select * from A.A", Collections.emptySet(), typeAA, null).hasNext());
- assertFalse(spi.query(typeAB.space(), "select * from A.B", Collections.emptySet(), typeAB, null).hasNext());
- assertFalse(spi.query(typeBA.space(), "select * from B.A", Collections.emptySet(), typeBA, null).hasNext());
-
- // Nothing to remove.
- assertFalse(spi.remove("A", new IndexingEntityAdapter<>(1, null)));
- assertFalse(spi.remove("B", new IndexingEntityAdapter<>(1, null)));
-
- spi.store(typeAA.space(), typeAA, entity(1), entity(aa(1, "Vasya", 10)), "v1".getBytes(), 0);
-
- assertEquals(1, spi.size(typeAA.space(), typeAA));
- assertEquals(0, spi.size(typeAB.space(), typeAB));
- assertEquals(0, spi.size(typeBA.space(), typeBA));
-
- spi.store(typeAB.space(), typeAB, entity(1), entity(ab(1, "Vasya", 20, "Some text about Vasya goes here.")),
- "v2".getBytes(), 0);
-
- // In one space all keys must be unique.
- assertEquals(0, spi.size(typeAA.space(), typeAA));
- assertEquals(1, spi.size(typeAB.space(), typeAB));
- assertEquals(0, spi.size(typeBA.space(), typeBA));
-
- spi.store(typeBA.space(), typeBA, entity(1), entity(ba(2, "Petya", 25, true)), "v3".getBytes(), 0);
-
- // No replacement because of different space.
- assertEquals(0, spi.size(typeAA.space(), typeAA));
- assertEquals(1, spi.size(typeAB.space(), typeAB));
- assertEquals(1, spi.size(typeBA.space(), typeBA));
-
- spi.store(typeBA.space(), typeBA, entity(1), entity(ba(2, "Kolya", 25, true)), "v4".getBytes(), 0);
-
- // Replacement in the same table.
- assertEquals(0, spi.size(typeAA.space(), typeAA));
- assertEquals(1, spi.size(typeAB.space(), typeAB));
- assertEquals(1, spi.size(typeBA.space(), typeBA));
-
- spi.store(typeAA.space(), typeAA, entity(2), entity(aa(2, "Valera", 19)), "v5".getBytes(), 0);
-
- assertEquals(1, spi.size(typeAA.space(), typeAA));
- assertEquals(1, spi.size(typeAB.space(), typeAB));
- assertEquals(1, spi.size(typeBA.space(), typeBA));
-
- spi.store(typeAA.space(), typeAA, entity(3), entity(aa(3, "Borya", 18)), "v6".getBytes(), 0);
-
- assertEquals(2, spi.size(typeAA.space(), typeAA));
- assertEquals(1, spi.size(typeAB.space(), typeAB));
- assertEquals(1, spi.size(typeBA.space(), typeBA));
-
- spi.store(typeAB.space(), typeAB, entity(4), entity(ab(4, "Vitalya", 20, "Very Good guy")), "v7".getBytes(), 0);
-
- assertEquals(2, spi.size(typeAA.space(), typeAA));
- assertEquals(2, spi.size(typeAB.space(), typeAB));
- assertEquals(1, spi.size(typeBA.space(), typeBA));
-
- // Query data.
- Iterator<IndexingKeyValueRow<Integer, Map<String, Object>>> res =
- spi.query(typeAA.space(), "select * from a order by age", Collections.emptySet(), typeAA, null);
-
- assertTrue(res.hasNext());
- assertEquals(aa(3, "Borya", 18), value(res.next()));
- assertTrue(res.hasNext());
- assertEquals(aa(2, "Valera", 19), value(res.next()));
- assertFalse(res.hasNext());
-
- res = spi.query(typeAB.space(), "select * from b order by name", Collections.emptySet(), typeAB, null);
-
- assertTrue(res.hasNext());
- assertEquals(ab(1, "Vasya", 20, "Some text about Vasya goes here."), value(res.next()));
- assertTrue(res.hasNext());
- assertEquals(ab(4, "Vitalya", 20, "Very Good guy"), value(res.next()));
- assertFalse(res.hasNext());
-
- res = spi.query(typeBA.space(), "select * from a", Collections.emptySet(), typeBA, null);
-
- assertTrue(res.hasNext());
- assertEquals(ba(2, "Kolya", 25, true), value(res.next()));
- assertFalse(res.hasNext());
-
- // Text queries
- Iterator<IndexingKeyValueRow<Integer, Map<String, Object>>> txtRes = spi.queryText(typeAB.space(), "good",
- typeAB, null);
-
- assertTrue(txtRes.hasNext());
- assertEquals(ab(4, "Vitalya", 20, "Very Good guy"), value(txtRes.next()));
- assertFalse(txtRes.hasNext());
-
- // Fields query
- IndexingFieldsResult fieldsRes =
- spi.queryFields(null, "select a.a.name n1, a.a.age a1, b.a.name n2, " +
- "b.a.age a2 from a.a, b.a where a.a.id = b.a.id ", Collections.emptySet(), null);
-
- String[] aliases = {"N1", "A1", "N2", "A2"};
- Object[] vals = { "Valera", 19, "Kolya", 25};
-
- assertTrue(fieldsRes.iterator().hasNext());
-
- List<IndexingEntity<?>> fields = fieldsRes.iterator().next();
-
- assertEquals(4, fields.size());
-
- int i = 0;
-
- for (IndexingEntity<?> f : fields) {
- assertEquals(aliases[i], fieldsRes.metaData().get(i).fieldName());
- assertEquals(vals[i++], f.value());
- }
-
- assertFalse(fieldsRes.iterator().hasNext());
-
- // Query on not existing table should not fail.
- assertFalse(spi.queryFields(null, "select * from not_existing_table",
- Collections.emptySet(), null).iterator().hasNext());
-
- // Remove
- spi.remove(typeAA.space(), entity(2));
-
- assertEquals(1, spi.size(typeAA.space(), typeAA));
- assertEquals(2, spi.size(typeAB.space(), typeAB));
- assertEquals(1, spi.size(typeBA.space(), typeBA));
-
- spi.remove(typeBA.space(), entity(1));
-
- assertEquals(1, spi.size(typeAA.space(), typeAA));
- assertEquals(2, spi.size(typeAB.space(), typeAB));
- assertEquals(0, spi.size(typeBA.space(), typeBA));
-
- boolean h2IdxOffheap = (spi instanceof GridH2IndexingSpi) &&
- ((GridH2IndexingSpiMBean)spi).getMaxOffHeapMemory() > 0;
-
- // At the time of this writing index rebuilding is not supported for GridH2IndexingSpi with off-heap storage.
- if (!h2IdxOffheap) {
- // Rebuild
-
- spi.rebuildIndexes(typeAB.space(), typeAB);
-
- assertEquals(1, spi.size(typeAA.space(), typeAA));
- assertEquals(2, spi.size(typeAB.space(), typeAB));
- assertEquals(0, spi.size(typeBA.space(), typeBA));
-
- // For invalid space name/type should not fail.
- spi.rebuildIndexes("not_existing_space", typeAA);
- spi.rebuildIndexes(typeAA.space(), new TypeDesc("C", "C", fieldsAA, null));
- }
-
- // Unregister.
- spi.unregisterType(typeAA.space(), typeAA);
-
- assertEquals(-1, spi.size(typeAA.space(), typeAA));
- assertEquals(2, spi.size(typeAB.space(), typeAB));
- assertEquals(0, spi.size(typeBA.space(), typeBA));
-
- spi.unregisterType(typeAB.space(), typeAB);
-
- assertEquals(-1, spi.size(typeAA.space(), typeAA));
- assertEquals(-1, spi.size(typeAB.space(), typeAB));
- assertEquals(0, spi.size(typeBA.space(), typeBA));
-
- spi.unregisterType(typeBA.space(), typeBA);
-
- // Should not store but should not fail as well.
- spi.store(typeAA.space(), typeAA, entity(10), entity(aa(1, "Fail", 100500)), "v220".getBytes(), 0);
-
- assertEquals(-1, spi.size(typeAA.space(), typeAA));
- }
-
- /**
- * Test long queries write explain warnings into log.
- *
- * @throws Exception If failed.
- */
- public void testLongQueries() throws Exception {
- X spi = getSpi();
-
- if (!(spi instanceof GridH2IndexingSpi))
- return;
-
- long longQryExecTime = 100;
-
- GridStringLogger log = new GridStringLogger(false, this.log);
-
- IgniteLogger oldLog = GridTestUtils.getFieldValue(spi, "log");
- ((GridH2IndexingSpi)spi).setLongQueryExecutionTimeout(longQryExecTime);
- ((GridH2IndexingSpi) spi).setLongQueryExplain(true);
-
- try {
- GridTestUtils.setFieldValue(spi, "log", log);
-
- String sql = "select sum(x) FROM SYSTEM_RANGE(?, ?)";
-
- long now = U.currentTimeMillis();
- long time = now;
-
- long range = 1000000L;
-
- while (now - time <= longQryExecTime * 3 / 2) {
- time = now;
- range *= 3;
-
- IndexingFieldsResult res = spi.queryFields(null, sql, Arrays.<Object>asList(1, range), null);
-
- assert res.iterator().hasNext();
-
- now = U.currentTimeMillis();
- }
-
- String res = log.toString();
-
- F.println(res);
-
- assert res.contains("/* PUBLIC.RANGE_INDEX */");
- }
- finally {
- GridTestUtils.setFieldValue(spi, "log", oldLog);
- ((GridH2IndexingSpi)spi).setLongQueryExecutionTimeout(3000);
- }
- }
-
- public void _testResultReuse() throws Exception {
- final X spi = getSpi();
-
- multithreaded(new Callable<Object>() {
- @Override public Object call() throws Exception {
- return spi.queryFields(null, "SELECT sum(x) + sum(x) + sum(x) + sum(x) FROM SYSTEM_RANGE(?, ?)",
- F.<Object>asList(0, 7000000), null);
- }
- }, 5);
- }
-
- /**
- * Test long queries write explain warnings into log.
- *
- * @throws Exception If failed.
- */
- public void testZeroLongQuery() throws Exception {
- X spi = getSpi();
-
- if (!(spi instanceof GridH2IndexingSpi))
- return;
-
- long longQryExecTime = -1;
-
- GridStringLogger log = new GridStringLogger(false, this.log);
-
- IgniteLogger oldLog = GridTestUtils.getFieldValue(spi, "log");
- ((GridH2IndexingSpi)spi).setLongQueryExecutionTimeout(longQryExecTime);
- ((GridH2IndexingSpi) spi).setLongQueryExplain(true);
-
- try {
- GridTestUtils.setFieldValue(spi, "log", log);
-
- String sql = "SELECT * FROM MyNonExistingTable";
-
- IndexingFieldsResult res = spi.queryFields(null, sql, Collections.emptyList(), null);
-
- assertFalse(res.iterator().hasNext());
-
- String logStr = log.toString();
-
- F.println(logStr);
-
- assertTrue(logStr.contains("Failed to explain plan because required table does not exist"));
- }
- finally {
- GridTestUtils.setFieldValue(spi, "log", oldLog);
- ((GridH2IndexingSpi)spi).setLongQueryExecutionTimeout(3000);
- }
- }
-
- /**
- * Index descriptor.
- */
- private static class TextIndex implements IndexDescriptor {
- /** */
- private final Collection<String> fields;
-
- /**
- * @param fields Fields.
- */
- private TextIndex(Collection<String> fields) {
- this.fields = Collections.unmodifiableCollection(fields);
- }
-
- /** {@inheritDoc} */
- @Override public Collection<String> fields() {
- return fields;
- }
-
- /** {@inheritDoc} */
- @Override public boolean descending(String field) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public IndexType type() {
- return IndexType.FULLTEXT;
- }
- }
-
- /**
- * Type descriptor.
- */
- private static class TypeDesc implements IndexingTypeDescriptor {
- /** */
- private final String name;
-
- /** */
- private final String space;
-
- /** */
- private final Map<String, Class<?>> valFields;
-
- /** */
- private final IndexDescriptor textIdx;
-
- /**
- * @param space Space name.
- * @param name Type name.
- * @param valFields Fields.
- * @param textIdx Fulltext index.
- */
- private TypeDesc(String space, String name, Map<String, Class<?>> valFields, IndexDescriptor textIdx) {
- this.name = name;
- this.space = space;
- this.valFields = Collections.unmodifiableMap(valFields);
- this.textIdx = textIdx;
- }
-
- /** {@inheritDoc} */
- @Override public String name() {
- return name;
- }
-
- /**
- * @return Space name.
- */
- public String space() {
- return space;
- }
-
- /** {@inheritDoc} */
- @Override public Map<String, Class<?>> valueFields() {
- return valFields;
- }
-
- /** {@inheritDoc} */
- @Override public Map<String, Class<?>> keyFields() {
- return Collections.emptyMap();
- }
-
- /** {@inheritDoc} */
- @Override public <T> T value(Object obj, String field) throws IgniteSpiException {
- assert obj != null;
- assert !F.isEmpty(field);
-
- return (T)((Map<String, Object>) obj).get(field);
- }
-
- /** */
- @Override public Map<String, IndexDescriptor> indexes() {
- return textIdx == null ? Collections.<String, IndexDescriptor>emptyMap() :
- Collections.singletonMap("index", textIdx);
- }
-
- /** */
- @Override public Class<?> valueClass() {
- return Object.class;
- }
-
- /** */
- @Override public Class<?> keyClass() {
- return Integer.class;
- }
-
- /** */
- @Override public boolean valueTextIndex() {
- return textIdx == null;
- }
- }
-
- /**
- * Indexing marshaller.
- */
- private static class IdxMarshaller implements IndexingMarshaller {
- /** */
- private final IgniteMarshaller marshaller;
-
- /**
- * @param marshaller Marshaller.
- */
- private IdxMarshaller(IgniteMarshaller marshaller) {
- this.marshaller = marshaller;
- }
-
- /** {@inheritDoc} */
- @Override public <T> IndexingEntity<T> unmarshal(byte[] bytes) throws IgniteSpiException {
- try {
- return new IndexingEntityAdapter<>(
- (T)marshaller.unmarshal(bytes, getClass().getClassLoader()), bytes);
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override public byte[] marshal(IndexingEntity<?> entity) throws IgniteSpiException {
- if (entity.bytes() != null)
- return entity.bytes();
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- try {
- marshaller.marshal(entity.value(), out);
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
-
- return out.toByteArray();
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexRebuildTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexRebuildTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexRebuildTest.java
deleted file mode 100644
index e9ec568..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexRebuildTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.apache.ignite.configuration.*;
-import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
-import org.gridgain.grid.kernal.processors.cache.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.testframework.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-/**
- */
-public class GridH2IndexRebuildTest extends GridCacheAbstractSelfTest {
- /** */
- private static final int GRID_CNT = 1;
-
- /** {@inheritDoc} */
- @Override protected int gridCount() {
- return GRID_CNT;
- }
-
- /**
- * Overrides rebuildIndexes to check it can be interrupted.
- */
- private static class SleepingH2Indexing extends GridH2IndexingSpi {
- /** */
- private volatile boolean sleepInRebuild;
-
- /** */
- private volatile boolean interrupted;
-
- /** {@inheritDoc} */
- @Override public void rebuildIndexes(@Nullable String spaceName, IndexingTypeDescriptor type) {
- if (sleepInRebuild) {
- try {
- U.sleep(Long.MAX_VALUE);
- }
- catch (GridInterruptedException ignored) {
- interrupted = true;
- }
- }
-
- super.rebuildIndexes(spaceName, type);
- }
- }
-
- /** */
- private static SleepingH2Indexing spi;
-
- /** {@inheritDoc} */
- @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
- IgniteConfiguration cfg = super.getConfiguration(gridName);
-
- spi = new SleepingH2Indexing();
-
- cfg.setIndexingSpi(spi);
-
- return cfg;
- }
-
- /**
- * Value class with regular and compound indexes.
- */
- @SuppressWarnings("UnusedDeclaration")
- private static class TestValue1 {
- /** */
- @GridCacheQuerySqlField(index = true)
- private long val1;
-
- /** */
- @GridCacheQuerySqlField(index = true)
- private String val2;
-
- /** */
- @GridCacheQuerySqlField(groups = "group1")
- private int val3;
-
- /** */
- @GridCacheQuerySqlField(groups = "group1")
- private int val4;
-
- /**
- */
- TestValue1(long val1, String val2, int val3, int val4) {
- this.val1 = val1;
- this.val2 = val2;
- this.val3 = val3;
- this.val4 = val4;
- }
- }
-
- /**
- * Value class with regular and text indexes.
- */
- @SuppressWarnings("UnusedDeclaration")
- private static class TestValue2 {
- /** */
- @GridCacheQuerySqlField(index = true)
- private long val1;
-
- /** */
- @GridCacheQueryTextField
- private String val2;
-
- /**
- */
- TestValue2(long val1, String val2) {
- this.val1 = val1;
- this.val2 = val2;
- }
- }
-
- /** */
- private static final int ENTRY_CNT = 10000;
-
- /**
- * @throws Exception if failed.
- */
- public void testRebuildIndexes() throws Exception {
- cache().queries().rebuildIndexes(ArrayList.class).get();
-
- cache().queries().rebuildAllIndexes().get();
-
- GridCache<Integer, TestValue1> cache1 = grid(0).cache(null);
- GridCache<Integer, TestValue2> cache2 = grid(0).cache(null);
-
- for (int i = 0; i < ENTRY_CNT; i++) {
- cache1.put(i, new TestValue1(i, "val2-" + i, i, i));
- cache2.put(ENTRY_CNT * 2 + i, new TestValue2(i, "val2-" + i));
- }
-
- GridCacheQuery<Map.Entry<Integer, TestValue1>> qry1 =
- cache1.queries().createSqlQuery(TestValue1.class, "val1 = 9000");
-
- GridCacheQuery<Map.Entry<Integer, TestValue1>> qry2 =
- cache1.queries().createSqlQuery(TestValue1.class, "val2 = 'val2-9000'");
-
- GridCacheQuery<Map.Entry<Integer, TestValue1>> qry3 =
- cache1.queries().createSqlQuery(TestValue1.class, "val3 = 9000 and val4 = 9000");
-
- GridCacheQuery<Map.Entry<Integer, TestValue2>> qry4 =
- cache2.queries().createSqlQuery(TestValue2.class, "val1 = 9000");
-
- GridCacheQuery<Map.Entry<Integer, TestValue2>> qry5 =
- cache2.queries().createFullTextQuery(TestValue2.class, "val2 = 'val2-9000'");
-
- checkQueryReturnsOneEntry(qry1, qry2, qry3, qry4, qry5);
-
- for (int i = 0; i < ENTRY_CNT / 2; i++) {
- cache1.remove(i);
- cache2.remove(ENTRY_CNT * 2 + i);
- }
-
- cache().queries().rebuildIndexes(TestValue1.class).get();
- cache().queries().rebuildIndexes(TestValue2.class).get();
-
- checkQueryReturnsOneEntry(qry1, qry2, qry3, qry4, qry5);
-
- cache().queries().rebuildAllIndexes().get();
-
- checkQueryReturnsOneEntry(qry1, qry2, qry3, qry4, qry5);
- }
-
- /**
- * @throws Exception if failed.
- */
- public void testRebuildInterrupted() throws Exception {
- spi.sleepInRebuild = true;
-
- GridCache<Integer, TestValue1> cache1 = grid(0).cache(null);
- GridCache<Integer, TestValue2> cache2 = grid(0).cache(null);
-
- cache1.put(0, new TestValue1(0, "val0", 0 ,0));
- cache2.put(1, new TestValue2(0, "val0"));
-
- checkCancel(grid(0).cache(null).queries().rebuildIndexes("TestValue1"));
-
- checkCancel(grid(0).cache(null).queries().rebuildAllIndexes());
-
- spi.sleepInRebuild = false;
-
- final IgniteFuture<?> fut1 = grid(0).cache(null).queries().rebuildIndexes(TestValue1.class);
-
- assertFalse(fut1.isCancelled());
-
- fut1.get();
-
- final IgniteFuture<?> fut2 = grid(0).cache(null).queries().rebuildAllIndexes();
-
- assertFalse(fut2.isCancelled());
-
- fut2.get();
- }
-
- /**
- * @throws Exception if failed.
- */
- private void checkCancel(final IgniteFuture<?> fut) throws Exception {
- assertTrue(fut.cancel());
-
- GridTestUtils.assertThrows(log, new Callable<Void>() {
- @Override
- public Void call() throws Exception {
- fut.get();
- return null;
- }
- }, IgniteFutureCancelledException.class, null);
-
- assertTrue(spi.interrupted);
-
- spi.interrupted = false;
- }
-
- /**
- * @throws Exception if failed.
- */
- private void checkQueryReturnsOneEntry(GridCacheQuery<?>... qrys) throws Exception {
- for (GridCacheQuery<?> qry : qrys)
- assertEquals(1, qry.execute().get().size());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiGeoSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiGeoSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiGeoSelfTest.java
deleted file mode 100644
index 969e414..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiGeoSelfTest.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import com.vividsolutions.jts.geom.*;
-import com.vividsolutions.jts.io.*;
-import org.apache.ignite.lang.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
-import org.gridgain.grid.kernal.processors.cache.*;
-import org.gridgain.grid.util.typedef.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.testframework.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-/**
- *
- */
-public class GridH2IndexingSpiGeoSelfTest extends GridCacheAbstractSelfTest {
- /** */
- private static final int CNT = 100;
-
- /** */
- private static final long DUR = 60000L;
-
- /** {@inheritDoc} */
- @Override protected int gridCount() {
- return 3;
- }
-
- /** {@inheritDoc} */
- @Override protected long getTestTimeout() {
- return DUR * 3;
- }
-
- /**
- * @throws Exception If failed.
- */
- @SuppressWarnings("unchecked")
- public void testGeo() throws Exception {
- GridCache<Integer, EnemyCamp> cache = grid(0).cache(null);
-
- WKTReader r = new WKTReader();
-
- cache.put(0, new EnemyCamp(r.read("POINT(25 75)"), "A"));
- cache.put(1, new EnemyCamp(r.read("POINT(70 70)"), "B"));
- cache.put(2, new EnemyCamp(r.read("POINT(70 30)"), "C"));
- cache.put(3, new EnemyCamp(r.read("POINT(75 25)"), "D"));
-
- GridCacheQuery<Map.Entry<Integer, EnemyCamp>> qry = cache.queries().createSqlQuery(EnemyCamp.class,
- "coords && ?");
-
- Collection<Map.Entry<Integer, EnemyCamp>> res = qry.execute(r.read("POLYGON((5 70, 5 80, 30 80, 30 70, 5 70))"))
- .get();
-
- checkPoints(res, "A");
-
- res = qry.execute(r.read("POLYGON((10 5, 10 35, 70 30, 75 25, 10 5))")).get();
-
- checkPoints(res, "C", "D");
-
- // Move B to the first polygon.
- cache.put(1, new EnemyCamp(r.read("POINT(20 75)"), "B"));
-
- res = qry.execute(r.read("POLYGON((5 70, 5 80, 30 80, 30 70, 5 70))")).get();
-
- checkPoints(res, "A", "B");
-
- // Move B to the second polygon.
- cache.put(1, new EnemyCamp(r.read("POINT(30 30)"), "B"));
-
- res = qry.execute(r.read("POLYGON((10 5, 10 35, 70 30, 75 25, 10 5))")).get();
-
- checkPoints(res, "B", "C", "D");
-
- // Remove B.
- cache.remove(1);
-
- res = qry.execute(r.read("POLYGON((5 70, 5 80, 30 80, 30 70, 5 70))")).get();
-
- checkPoints(res, "A");
-
- res = qry.execute(r.read("POLYGON((10 5, 10 35, 70 30, 75 25, 10 5))")).get();
-
- checkPoints(res, "C", "D");
-
- // Check explaint request.
- assertTrue(F.first(cache.queries().createSqlFieldsQuery("explain select * from EnemyCamp " +
- "where coords && 'POINT(25 75)'").execute().get()).get(0).toString().contains("coords_idx"));
- }
-
- /**
- * @throws Exception If failed.
- */
- @SuppressWarnings("unchecked")
- public void testGeoMultithreaded() throws Exception {
- final GridCache<Integer, EnemyCamp> cache1 = grid(0).cache(null);
- final GridCache<Integer, EnemyCamp> cache2 = grid(1).cache(null);
- final GridCache<Integer, EnemyCamp> cache3 = grid(2).cache(null);
-
- final String[] points = new String[CNT];
-
- WKTReader r = new WKTReader();
-
- ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
- for (int idx = 0; idx < CNT; idx++) {
- int x = rnd.nextInt(1, 100);
- int y = rnd.nextInt(1, 100);
-
- cache1.put(idx, new EnemyCamp(r.read("POINT(" + x + " " + y + ")"), Integer.toString(idx)));
-
- points[idx] = Integer.toString(idx);
- }
-
- Thread.sleep(200);
-
- final AtomicBoolean stop = new AtomicBoolean();
- final AtomicReference<Exception> err = new AtomicReference<>();
-
- IgniteFuture<?> putFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
- @Override public Void call() throws Exception {
- WKTReader r = new WKTReader();
-
- ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
- while (!stop.get()) {
- int cacheIdx = rnd.nextInt(0, 3);
-
- GridCache<Integer, EnemyCamp> cache = cacheIdx == 0 ? cache1 : cacheIdx == 1 ? cache2 : cache3;
-
- int idx = rnd.nextInt(CNT);
- int x = rnd.nextInt(1, 100);
- int y = rnd.nextInt(1, 100);
-
- cache.put(idx, new EnemyCamp(r.read("POINT(" + x + " " + y + ")"), Integer.toString(idx)));
-
- U.sleep(50);
- }
-
- return null;
- }
- }, Runtime.getRuntime().availableProcessors(), "put-thread");
-
- IgniteFuture<?> qryFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
- @Override public Void call() throws Exception {
- WKTReader r = new WKTReader();
-
- ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
- while (!stop.get()) {
- try {
- int cacheIdx = rnd.nextInt(0, 3);
-
- GridCache<Integer, EnemyCamp> cache = cacheIdx == 0 ? cache1 : cacheIdx == 1 ? cache2 : cache3;
-
- GridCacheQuery<Map.Entry<Integer, EnemyCamp>> qry = cache.queries().createSqlQuery(
- EnemyCamp.class, "coords && ?");
-
- Collection<Map.Entry<Integer, EnemyCamp>> res = qry.execute(
- r.read("POLYGON((0 0, 0 100, 100 100, 100 0, 0 0))")).get();
-
- checkPoints(res, points);
-
- U.sleep(5);
- }
- catch (Exception e) {
- err.set(e);
-
- stop.set(true);
-
- break;
- }
- }
-
- return null;
- }
- }, 4, "qry-thread");
-
- U.sleep(60000L);
-
- stop.set(true);
-
- putFut.get();
- qryFut.get();
-
- Exception err0 = err.get();
-
- if (err0 != null)
- throw err0;
- }
-
- /**
- * Check whether result contains all required points.
- *
- * @param res Result.
- * @param points Expected points.
- */
- private void checkPoints( Collection<Map.Entry<Integer, EnemyCamp>> res, String... points) {
- Set<String> set = new HashSet<>(Arrays.asList(points));
-
- assertEquals(set.size(), res.size());
-
- for (Map.Entry<Integer, EnemyCamp> e : res)
- assertTrue(set.remove(e.getValue().name));
- }
-
- /**
- *
- */
- private static class EnemyCamp implements Serializable {
- /** */
- @GridCacheQuerySqlField(index = true)
- private Geometry coords;
-
- /** */
- @GridCacheQuerySqlField
- private String name;
-
- /**
- * @param coords Coordinates.
- * @param name Name.
- */
- private EnemyCamp(Geometry coords, String name) {
- this.coords = coords;
- this.name = name;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemSelfTest.java
deleted file mode 100644
index dacaa52..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemSelfTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.gridgain.grid.spi.indexing.*;
-import org.gridgain.testframework.junits.spi.*;
-
-/**
- * Tests for H2 indexing SPI.
- */
-@GridSpiTest(spi = GridH2IndexingSpi.class, group = "Indexing SPI")
-public class GridH2IndexingSpiInMemSelfTest extends GridIndexingSpiAbstractSelfTest<GridH2IndexingSpi> {
- // No-op.
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemStartStopSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemStartStopSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemStartStopSelfTest.java
deleted file mode 100644
index 98ec281..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiInMemStartStopSelfTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.gridgain.grid.spi.*;
-import org.gridgain.testframework.junits.spi.*;
-
-/**
- * Start/stop tests for H2 indexing SPI.
- */
-@GridSpiTest(spi = GridH2IndexingSpi.class, group = "Indexing SPI")
-public class GridH2IndexingSpiInMemStartStopSelfTest extends GridSpiStartStopAbstractTest<GridH2IndexingSpi>{
- // No-op.
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapSelfTest.java
deleted file mode 100644
index f08e4c9..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapSelfTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.gridgain.grid.spi.indexing.*;
-import org.gridgain.testframework.junits.spi.*;
-
-/**
- * Tests for H2 indexing SPI.
- */
-@GridSpiTest(spi = GridH2IndexingSpi.class, group = "Indexing SPI")
-public class GridH2IndexingSpiOffheapSelfTest extends GridIndexingSpiAbstractSelfTest<GridH2IndexingSpi> {
- /** */
- private static final long offheap = 10000000;
-
- private static GridH2IndexingSpi currentSpi;
-
- /** {@inheritDoc} */
- @Override protected void spiConfigure(GridH2IndexingSpi spi) throws Exception {
- super.spiConfigure(spi);
-
- spi.setMaxOffHeapMemory(offheap);
-
- currentSpi = spi;
- }
-
- /** {@inheritDoc} */
- @Override protected void afterSpiStopped() throws Exception {
- super.afterSpiStopped();
-
- assertEquals(0, currentSpi.getAllocatedOffHeapMemory());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapStartStopSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapStartStopSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapStartStopSelfTest.java
deleted file mode 100644
index 9a82977..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiOffheapStartStopSelfTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.gridgain.grid.spi.*;
-import org.gridgain.testframework.junits.spi.*;
-
-/**
- * Start/stop tests for H2 indexing SPI.
- */
-@GridSpiTest(spi = GridH2IndexingSpi.class, group = "Indexing SPI")
-public class GridH2IndexingSpiOffheapStartStopSelfTest extends GridSpiStartStopAbstractTest<GridH2IndexingSpi>{
- /** */
- private static final long offheap = 10000000;
-
- private static GridH2IndexingSpi currentSpi;
-
- /** {@inheritDoc} */
- protected void spiConfigure(GridH2IndexingSpi spi) throws Exception {
- super.spiConfigure(spi);
-
- spi.setMaxOffHeapMemory(offheap);
-
- currentSpi = spi;
- }
-
- /** {@inheritDoc} */
- @Override protected void afterSpiStopped() throws Exception {
- super.afterSpiStopped();
-
- assertEquals(0, currentSpi.getAllocatedOffHeapMemory());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TableSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TableSelfTest.java
deleted file mode 100644
index ee112f1..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TableSelfTest.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.gridgain.testframework.junits.common.*;
-import org.h2.Driver;
-import org.h2.index.*;
-import org.h2.result.*;
-import org.h2.table.*;
-import org.h2.value.*;
-import org.jetbrains.annotations.*;
-import org.junit.*;
-
-import java.sql.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-/**
- * Tests H2 Table.
- */
-@SuppressWarnings({"TypeMayBeWeakened", "FieldAccessedSynchronizedAndUnsynchronized"})
-public class GridH2TableSelfTest extends GridCommonAbstractTest {
- /** */
- private static final long MAX_X = 2000;
-
- /** */
- private static final String DB_URL = "jdbc:h2:mem:gg_table_engine;MULTI_THREADED=1;OPTIMIZE_REUSE_RESULTS=0;" +
- "QUERY_CACHE_SIZE=0;RECOMPILE_ALWAYS=1";
-
- /** */
- private static final String CREATE_TABLE_SQL = "CREATE TABLE T(ID UUID, T TIMESTAMP, STR VARCHAR, X BIGINT)";
-
- /** */
- private static final String PK_NAME = "__GG_PK_";
-
- /** */
- private static final String STR_IDX_NAME = "__GG_IDX_";
-
- /** */
- private static final String NON_UNIQUE_IDX_NAME = "__GG_IDX_";
-
- /** */
- private static final String SCAN_IDX_NAME = GridH2Table.ScanIndex.SCAN_INDEX_NAME_SUFFIX;
-
- /** */
- private Connection conn;
-
- /** */
- private GridH2Table tbl;
-
- /** {@inheritDoc} */
- @Override protected void beforeTest() throws Exception {
- Driver.load();
-
- conn = DriverManager.getConnection(DB_URL);
-
- tbl = GridH2Table.Engine.createTable(conn, CREATE_TABLE_SQL, null, new GridH2Table.IndexesFactory() {
- @Override public ArrayList<Index> createIndexes(GridH2Table tbl) {
- ArrayList<Index> idxs = new ArrayList<>();
-
- IndexColumn id = tbl.indexColumn(0, SortOrder.ASCENDING);
- IndexColumn t = tbl.indexColumn(1, SortOrder.ASCENDING);
- IndexColumn str = tbl.indexColumn(2, SortOrder.DESCENDING);
- IndexColumn x = tbl.indexColumn(3, SortOrder.DESCENDING);
-
- idxs.add(new GridH2TreeIndex(PK_NAME, tbl, true, 0, 1, id));
- idxs.add(new GridH2TreeIndex(NON_UNIQUE_IDX_NAME, tbl, false, 0, 1, x, t));
- idxs.add(new GridH2TreeIndex(STR_IDX_NAME, tbl, false, 0, 1, str));
-
- return idxs;
- }
- }, null);
- }
-
- /** {@inheritDoc} */
- @Override protected void afterTest() throws Exception {
- conn.close();
-
- conn = null;
- tbl = null;
- }
-
- /**
- * @param id Id.
- * @param t Timestamp.
- * @param str String.
- * @param x X.
- * @return New row.
- */
- private GridH2Row row(UUID id, long t, String str, long x) {
- return new GridH2Row(ValueUuid.get(id.getMostSignificantBits(), id.getLeastSignificantBits()),
- ValueTimestamp.get(new Timestamp(t)),
- ValueString.get(str),
- ValueLong.get(x));
- }
-
-
- /**
- * Simple table test.
- *
- * @throws Exception If failed.
- */
- public void testTable() throws Exception {
- // Test insert.
- long x = MAX_X;
-
- Random rnd = new Random();
-
- while(x-- > 0) {
- UUID id = UUID.randomUUID();
-
- GridH2Row row = row(id, System.currentTimeMillis(), rnd.nextBoolean() ? id.toString() :
- UUID.randomUUID().toString(), rnd.nextInt(100));
-
- tbl.doUpdate(row, false);
- }
-
- assertEquals(MAX_X, tbl.getRowCountApproximation());
- assertEquals(MAX_X, tbl.getRowCount(null));
-
- for (GridH2IndexBase idx : tbl.indexes()) {
- assertEquals(MAX_X, idx.getRowCountApproximation());
- assertEquals(MAX_X, idx.getRowCount(null));
- }
-
- // Check correct rows order.
- checkOrdered((GridH2TreeIndex)tbl.indexes().get(0), new Comparator<SearchRow>() {
- @Override public int compare(SearchRow o1, SearchRow o2) {
- UUID id1 = (UUID)o1.getValue(0).getObject();
- UUID id2 = (UUID)o2.getValue(0).getObject();
-
- return id1.compareTo(id2);
- }
- });
-
- checkOrdered((GridH2TreeIndex)tbl.indexes().get(1), new Comparator<SearchRow>() {
- @Override public int compare(SearchRow o1, SearchRow o2) {
- Long x1 = (Long)o1.getValue(3).getObject();
- Long x2 = (Long)o2.getValue(3).getObject();
-
- int c = x2.compareTo(x1);
-
- if (c != 0)
- return c;
-
- Timestamp t1 = (Timestamp)o1.getValue(1).getObject();
- Timestamp t2 = (Timestamp)o2.getValue(1).getObject();
-
- return t1.compareTo(t2);
- }
- });
-
- checkOrdered((GridH2TreeIndex)tbl.indexes().get(2), new Comparator<SearchRow>() {
- @Override public int compare(SearchRow o1, SearchRow o2) {
- String s1 = (String)o1.getValue(2).getObject();
- String s2 = (String)o2.getValue(2).getObject();
-
- return s2.compareTo(s1);
- }
- });
-
- // Indexes data consistency.
- ArrayList<? extends Index> idxs = tbl.indexes();
-
- checkIndexesConsistent((ArrayList<Index>)idxs, null);
-
- // Check unique index.
- UUID id = UUID.randomUUID();
- UUID id2 = UUID.randomUUID();
-
- assertTrue(tbl.doUpdate(row(id, System.currentTimeMillis(), id.toString(), rnd.nextInt(100)), false));
- assertTrue(tbl.doUpdate(row(id2, System.currentTimeMillis(), id2.toString(), rnd.nextInt(100)), false));
-
- // Check index selection.
- checkQueryPlan(conn, "SELECT * FROM T", SCAN_IDX_NAME);
-
- checkQueryPlan(conn, "SELECT * FROM T WHERE ID IS NULL", PK_NAME);
- checkQueryPlan(conn, "SELECT * FROM T WHERE ID = RANDOM_UUID()", PK_NAME);
- checkQueryPlan(conn, "SELECT * FROM T WHERE ID > RANDOM_UUID()", PK_NAME);
- checkQueryPlan(conn, "SELECT * FROM T ORDER BY ID", PK_NAME);
-
- checkQueryPlan(conn, "SELECT * FROM T WHERE STR IS NULL", STR_IDX_NAME);
- checkQueryPlan(conn, "SELECT * FROM T WHERE STR = 'aaaa'", STR_IDX_NAME);
- checkQueryPlan(conn, "SELECT * FROM T WHERE STR > 'aaaa'", STR_IDX_NAME);
- checkQueryPlan(conn, "SELECT * FROM T ORDER BY STR DESC", STR_IDX_NAME);
-
- checkQueryPlan(conn, "SELECT * FROM T WHERE X IS NULL", NON_UNIQUE_IDX_NAME);
- checkQueryPlan(conn, "SELECT * FROM T WHERE X = 10000", NON_UNIQUE_IDX_NAME);
- checkQueryPlan(conn, "SELECT * FROM T WHERE X > 10000", NON_UNIQUE_IDX_NAME);
- checkQueryPlan(conn, "SELECT * FROM T ORDER BY X DESC", NON_UNIQUE_IDX_NAME);
- checkQueryPlan(conn, "SELECT * FROM T ORDER BY X DESC, T", NON_UNIQUE_IDX_NAME);
-
- checkQueryPlan(conn, "SELECT * FROM T ORDER BY T, X DESC", SCAN_IDX_NAME);
-
- // Simple queries.
-
- Statement s = conn.createStatement();
-
- ResultSet rs = s.executeQuery("select id from t where x between 0 and 100");
-
- int i = 0;
- while (rs.next())
- i++;
-
- assertEquals(MAX_X + 2, i);
-
- // -----
-
- rs = s.executeQuery("select id from t where t is not null");
-
- i = 0;
- while (rs.next())
- i++;
-
- assertEquals(MAX_X + 2, i);
-
- // ----
-
- int cnt = 10 + rnd.nextInt(25);
-
- long t = System.currentTimeMillis();
-
- for (i = 0; i < cnt; i++) {
- id = UUID.randomUUID();
-
- assertTrue(tbl.doUpdate(row(id, t, id.toString(), 51), false));
- }
-
- rs = s.executeQuery("select x, id from t where x = 51 limit " + cnt);
-
- i = 0;
-
- while (rs.next()) {
- assertEquals(51, rs.getInt(1));
-
- i++;
- }
-
- assertEquals(cnt, i);
- }
-
- /**
- * Dumps all table rows for index.
- *
- * @param idx Index.
- */
- private void dumpRows(GridH2TreeIndex idx) {
- Iterator<GridH2Row> iter = idx.rows();
-
- while (iter.hasNext())
- System.out.println(iter.next().toString());
- }
-
- /**
- * Multithreaded indexes consistency test.
- *
- * @throws Exception If failed.
- */
- public void testIndexesMultiThreadedConsistency() throws Exception {
- final int threads = 19;
- final int iterations = 1500;
-
- multithreaded(new Callable<Void>() {
- @Override public Void call() throws Exception {
- Random rnd = new Random();
-
- PreparedStatement ps1 = null;
-
- for (int i = 0; i < iterations; i++) {
- UUID id = UUID.randomUUID();
-
- int x = rnd.nextInt(50);
-
- long t = System.currentTimeMillis();
-
- GridH2Row row = row(id, t, rnd.nextBoolean() ? id.toString() : UUID.randomUUID().toString(), x);
-
- assertTrue(tbl.doUpdate(row, false));
-
- if (rnd.nextInt(100) == 0) {
- tbl.lock(null, false, false);
-
- long cnt = 0;
-
- try {
- ArrayList<Index> idxs = tbl.getIndexes();
-
- // Consistency check.
- Set<Row> rowSet = checkIndexesConsistent(idxs, null);
-
- // Order check.
- checkOrdered(idxs);
-
- checkIndexesConsistent(idxs, rowSet);
-
- cnt = idxs.get(0).getRowCount(null);
- }
- finally {
- tbl.unlock(null);
- }
-
- // Row count is valid.
- ResultSet rs = conn.createStatement().executeQuery("select count(*) from t");
-
- assertTrue(rs.next());
-
- int cnt2 = rs.getInt(1);
-
- rs.close();
-
- assertTrue(cnt2 + " must be >= " + cnt, cnt2 >= cnt);
- assertTrue(cnt2 <= threads * iterations);
-
- // Search by ID.
- rs = conn.createStatement().executeQuery("select * from t where id = '" + id.toString() + "'");
-
- assertTrue(rs.next());
- assertFalse(rs.next());
-
- rs.close();
-
- // Scan search.
- if (ps1 == null)
- ps1 = conn.prepareStatement("select id from t where x = ? order by t desc");
-
- ps1.setInt(1, x);
-
- rs = ps1.executeQuery();
-
- for (;;) {
- assertTrue(rs.next());
-
- if (rs.getObject(1).equals(id))
- break;
- }
-
- rs.close();
- }
- }
- return null;
- }
- }, threads);
- }
-
- /**
- * Run test in endless loop.
- *
- * @param args Arguments.
- * @throws Exception If failed.
- */
- @SuppressWarnings("InfiniteLoopStatement")
- public static void main(String ... args) throws Exception {
- for (int i = 0;;) {
- GridH2TableSelfTest t = new GridH2TableSelfTest();
-
- t.beforeTest();
-
- t.testDataLoss();
-
- t.afterTest();
-
- System.out.println("..." + ++i);
- }
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testRangeQuery() throws Exception {
- int rows = 3000;
- int xs = 37;
-
- long t = System.currentTimeMillis();
-
- Random rnd = new Random();
-
- for (int i = 0 ; i < rows; i++) {
- UUID id = UUID.randomUUID();
-
- GridH2Row row = row(id, t++, id.toString(), rnd.nextInt(xs));
-
- assertTrue(tbl.doUpdate(row, false));
- }
-
- PreparedStatement ps = conn.prepareStatement("select count(*) from t where x = ?");
-
- int cnt = 0;
-
- for (int x = 0; x < xs; x++) {
- ps.setInt(1, x);
-
- ResultSet rs = ps.executeQuery();
-
- assertTrue(rs.next());
-
- cnt += rs.getInt(1);
- }
-
- assertEquals(rows, cnt);
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testDataLoss() throws Exception {
- final int threads = 37;
- final int iterations = 15000;
-
- final AtomicInteger cntr = new AtomicInteger();
-
- final UUID[] ids = new UUID[threads * iterations];
-
- for (int i = 0; i < ids.length; i++)
- ids[i] = UUID.randomUUID();
-
- final long t = System.currentTimeMillis();
-
- final AtomicInteger deleted = new AtomicInteger();
-
- multithreaded(new Callable<Void>() {
- @Override public Void call() throws Exception {
- Random rnd = new Random();
-
- int offset = cntr.getAndIncrement() * iterations;
-
- synchronized (ids[offset]) {
- for (int i = 0; i < iterations; i++) {
- UUID id = ids[offset + i];
-
- int x = rnd.nextInt(50);
-
- GridH2Row row = row(id, t, id.toString(), x);
-
- assertTrue(tbl.doUpdate(row, false));
- }
- }
-
- offset = (offset + iterations) % ids.length;
-
- synchronized (ids[offset]) {
- for (int i = 0; i < iterations; i += 2) {
- UUID id = ids[offset + i];
-
- int x = rnd.nextInt(50);
-
- GridH2Row row = row(id, t, id.toString(), x);
-
- if (tbl.doUpdate(row, true))
- deleted.incrementAndGet();
- }
- }
-
- return null;
- }
- }, threads);
-
- assertTrue(deleted.get() > 0);
-
- PreparedStatement p = conn.prepareStatement("select count(*) from t where id = ?");
-
- for (int i = 1; i < ids.length; i += 2) {
- p.setObject(1, ids[i]);
-
- ResultSet rs = p.executeQuery();
-
- assertTrue(rs.next());
-
- assertEquals(1, rs.getInt(1));
- }
-
- Statement s = conn.createStatement();
-
- ResultSet rs = s.executeQuery("select count(*) from t");
-
- assertTrue(rs.next());
-
- assertEquals(ids.length - deleted.get(), rs.getInt(1));
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testRebuildIndexes() throws Exception {
- ArrayList<GridH2IndexBase> idxsBefore = tbl.indexes();
-
- assertEquals(3, idxsBefore.size());
-
- Random rnd = new Random();
-
- for (int i = 0; i < MAX_X; i++) {
- UUID id = UUID.randomUUID();
-
- GridH2Row row = row(id, System.currentTimeMillis(), rnd.nextBoolean() ? id.toString() :
- UUID.randomUUID().toString(), rnd.nextInt(100));
-
- tbl.doUpdate(row, false);
- }
-
- for (GridH2IndexBase idx : idxsBefore)
- assertEquals(MAX_X, idx.getRowCountApproximation());
-
- tbl.rebuildIndexes();
-
- ArrayList<GridH2IndexBase> idxsAfter = tbl.indexes();
-
- assertEquals(3, idxsAfter.size());
-
- for (int i = 0; i < 3; i++) {
- GridH2IndexBase idxBefore = idxsBefore.get(i);
- GridH2IndexBase idxAfter = idxsAfter.get(i);
-
- assertNotSame(idxBefore, idxAfter);
- assertEquals(idxBefore.getName(), idxAfter.getName());
- assertSame(idxBefore.getTable(), idxAfter.getTable());
- assertEquals(idxBefore.getRowCountApproximation(), idxAfter.getRowCountApproximation());
- assertEquals(idxBefore.getIndexType().isUnique(), idxAfter.getIndexType().isUnique());
- Assert.assertArrayEquals(idxBefore.getColumns(), idxAfter.getColumns());
- }
- }
-
- /**
- * Check query plan to correctly select index.
- *
- * @param conn Connection.
- * @param sql Select.
- * @param search Search token in result.
- * @throws SQLException If failed.
- */
- private void checkQueryPlan(Connection conn, String sql, String search) throws SQLException {
-
- try (Statement s = conn.createStatement()) {
- try (ResultSet r = s.executeQuery("EXPLAIN ANALYZE " + sql)) {
- assertTrue(r.next());
-
- String plan = r.getString(1);
-
- assertTrue("Execution plan for '" + sql + "' query should contain '" + search + "'",
- plan.contains(search));
- }
- }
- }
-
- /**
- * @param idxs Indexes.
- * @param rowSet Rows.
- * @return Rows.
- */
- private Set<Row> checkIndexesConsistent(ArrayList<Index> idxs, @Nullable Set<Row> rowSet) {
- for (Index idx : idxs) {
- if (!(idx instanceof GridH2TreeIndex))
- continue;
-
- Set<Row> set = new HashSet<>();
-
- Iterator<GridH2Row> iter = ((GridH2TreeIndex)idx).rows();
-
- while(iter.hasNext())
- assertTrue(set.add(iter.next()));
-
- //((GridH2SnapTreeSet)((GridH2Index)idx).tree).print();
-
- if (rowSet == null)
- rowSet = set;
- else
- assertEquals(rowSet, set);
- }
-
- return rowSet;
- }
-
- /**
- * @param idxs Indexes list.
- */
- private void checkOrdered(ArrayList<Index> idxs) {
- for (Index idx : idxs) {
- if (!(idx instanceof GridH2TreeIndex))
- continue;
-
- GridH2TreeIndex h2Idx = (GridH2TreeIndex)idx;
-
- checkOrdered(h2Idx, h2Idx);
- }
- }
-
- /**
- * @param idx Index.
- * @param cmp Comparator.
- */
- private void checkOrdered(GridH2TreeIndex idx, Comparator<? super GridH2Row> cmp) {
- Iterator<GridH2Row> rows = idx.rows();
-
- GridH2Row min = null;
-
- while (rows.hasNext()) {
- GridH2Row row = rows.next();
-
- assertNotNull(row);
-
- assertFalse("Incorrect row order in index: " + idx + "\n min: " + min + "\n row: " + row,
- min != null && cmp.compare(min, row) > 0);
-
- min = row;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndexLoadTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndexLoadTest.java b/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndexLoadTest.java
deleted file mode 100644
index 48767e4..0000000
--- a/modules/indexing/src/test/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndexLoadTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.ignite.marshaller.optimized.*;
-import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.indexing.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.typedef.*;
-
-import java.io.*;
-import java.util.*;
-
-/**
- *
- */
-public class GridLuceneIndexLoadTest {
- /**
- * @param args Arguments.
- */
- @SuppressWarnings("ZeroLengthArrayAllocation")
- public static void main(String ... args) throws IgniteSpiException, FileNotFoundException {
- final IgniteOptimizedMarshaller m = new IgniteOptimizedMarshaller();
-
- IndexingTypeDescriptor desc = new IndexingTypeDescriptor() {
- @Override public String name() {
- return "StrType";
- }
-
- @Override public Map<String, Class<?>> valueFields() {
- throw new IllegalStateException();
- }
-
- @Override public Map<String, Class<?>> keyFields() {
- throw new IllegalStateException();
- }
-
- @Override public <T> T value(Object obj, String field) {
- throw new IllegalStateException();
- }
-
- @Override public Map<String, IndexDescriptor> indexes() {
- return Collections.<String, IndexDescriptor>singletonMap("txt_idx", new IndexDescriptor() {
- @Override public Collection<String> fields() {
- return Collections.emptyList();
- }
-
- @Override public boolean descending(String field) {
- return false;
- }
-
- @Override public IndexType type() {
- return IndexType.FULLTEXT;
- }
- });
- }
-
- @Override public Class<?> valueClass() {
- return String.class;
- }
-
- @Override public Class<?> keyClass() {
- return Integer.class;
- }
-
- @Override public boolean valueTextIndex() {
- return true;
- }
- };
-
- GridLuceneIndex idx = new GridLuceneIndex(new IndexingMarshaller() {
- @Override public <T> IndexingEntity<T> unmarshal(byte[] bytes) throws IgniteSpiException {
- try {
- return new IndexingEntityAdapter<>(m.<T>unmarshal(bytes, null), bytes);
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
- }
-
- @Override public byte[] marshal(IndexingEntity<?> entity) throws IgniteSpiException {
- try {
- return m.marshal(entity.value());
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
- }
- }, null, "spac", desc, false);
-
- ArrayList<String> ws = words("C:\\Users\\svladykin\\YandexDisk\\www\\CSW07-british-dict");
-
- byte[] ver = new byte[0];
-
- Random rnd = new Random();
-
- long begin = System.currentTimeMillis();
-
- for (int i = 0, len = 10000000 ; i < len; i++) {
- idx.store(new IndexingEntityAdapter<>(i, null),
- new IndexingEntityAdapter<Object>(sentence(rnd, ws), null),
- ver, 0L);
-
- if (i % 10000 == 0) {
- long time = System.currentTimeMillis();
-
- X.println(i + " " + (time - begin) + "ms " + GridLuceneFile.filesCnt.get());
-
- begin = time;
- }
- }
- }
-
- /**
- * @param rnd Random.
- * @param ws Words.
- * @return Sentence.
- */
- static String sentence(Random rnd, ArrayList<String> ws) {
- StringBuilder b = new StringBuilder();
-
- for (int i = 0, wordCnt = 1 + rnd.nextInt(8); i < wordCnt; i++) {
- if (i != 0)
- b.append(' ');
-
- b.append(ws.get(rnd.nextInt(ws.size())));
- }
-
- return b.toString();
- }
-
- /**
- * @param file File.
- * @return Words list.
- * @throws FileNotFoundException If failed.
- */
- static ArrayList<String> words(String file) throws FileNotFoundException {
- Scanner scan = new Scanner(new File(file));
-
- ArrayList<String> res = new ArrayList<>(270000);
-
- while (scan.hasNextLine()) {
- String line = scan.nextLine();
-
- int space = line.indexOf(' ');
-
- if (space > 0)
- line = line.substring(0, space);
-
- res.add(line.toLowerCase());
- }
-
- return res;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/loadtests/h2indexing/GridH2IndexingSpiLoadTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/loadtests/h2indexing/GridH2IndexingSpiLoadTest.java b/modules/indexing/src/test/java/org/gridgain/loadtests/h2indexing/GridH2IndexingSpiLoadTest.java
deleted file mode 100644
index c367463..0000000
--- a/modules/indexing/src/test/java/org/gridgain/loadtests/h2indexing/GridH2IndexingSpiLoadTest.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.loadtests.h2indexing;
-
-import org.apache.ignite.*;
-import org.apache.ignite.configuration.*;
-import org.apache.ignite.marshaller.optimized.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
-import org.apache.ignite.spi.discovery.tcp.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
-import org.gridgain.grid.util.typedef.*;
-import org.gridgain.grid.util.typedef.internal.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-import static org.apache.ignite.events.IgniteEventType.*;
-import static org.gridgain.grid.cache.GridCacheDistributionMode.*;
-import static org.gridgain.grid.cache.GridCacheWriteSynchronizationMode.*;
-
-/**
- * Indexing performance test.
- */
-public class GridH2IndexingSpiLoadTest {
- /**
- * Gets property as {@code int}.
- *
- * @param p Properties.
- * @param key Key.
- * @param dflt Default value.
- * @return Value for key.
- */
- private static int getInt(Properties p, String key, int dflt) {
- String val = p.getProperty(key);
-
- return val == null ? dflt : Integer.parseInt(val);
- }
-
- /**
- * Gets property as long.
- *
- * @param p Properties.
- * @param key Key.
- * @param dflt Default value.
- * @return Value for key.
- */
- private static long getLong(Properties p, String key, long dflt) {
- String val = p.getProperty(key);
-
- return val == null ? dflt : Long.parseLong(val);
- }
-
- /**
- * Loads configuration for test.
- *
- * @return Properties.
- * @throws IOException if failed.
- */
- private static Properties loadProperties() throws IOException {
- Properties p = new Properties();
-
- File propsFile = new File("idx-test.properties");
-
- if (propsFile.exists() && propsFile.isFile())
- p.load(new FileReader(propsFile));
- else
- System.out.println("Properties file not found.");
-
- return p;
- }
-
- /**
- * Main method.
- *
- * @param args Arguments.
- * @throws GridException If failed.
- * @throws IOException If failed.
- */
- @SuppressWarnings("InfiniteLoopStatement")
- public static void main(String...args) throws GridException, IOException {
- final Properties p = loadProperties();
-
- final int MAX_SIZE = getInt(p, "max-entries-count", 500000);
- final int MAX_NAMES = getInt(p, "max-names-count", 100);
-
- IgniteConfiguration c = new IgniteConfiguration();
-
- TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
-
- discoSpi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
-
- c.setDiscoverySpi(discoSpi);
-
- IgniteOptimizedMarshaller m = new IgniteOptimizedMarshaller();
-
- m.setClassNames(F.asList(GridTestEntity.class.getName()));
-
- c.setMarshaller(m);
-
- GridH2IndexingSpi indexing = new GridH2IndexingSpi();
-
- long offheap = getLong(p, "offheap-size", 3000000000L);
-
- if (1 == getInt(p, "offheap-enabled", 1))
- indexing.setMaxOffHeapMemory(offheap);
-
- boolean enableIndexing = 1 == getInt(p, "indexing-enabled", 1);
-
- if (enableIndexing)
- c.setIndexingSpi(indexing);
-
- GridCacheConfiguration cc = new GridCacheConfiguration();
-
- cc.setName("local");
- cc.setCacheMode(GridCacheMode.LOCAL);
- cc.setStartSize(MAX_SIZE);
- cc.setWriteSynchronizationMode(FULL_SYNC);
- // TODO enable evictions
-// cc.setEvictionPolicy(new GridCacheFifoEvictionPolicy(getInt(p, "not-evict-count", 100000)));
- cc.setQueryIndexEnabled(enableIndexing);
- cc.setDistributionMode(PARTITIONED_ONLY);
- cc.setStoreValueBytes(false);
- cc.setSwapEnabled(false);
- cc.setOffHeapMaxMemory(0);
-
- c.setCacheConfiguration(cc);
- c.setIncludeEventTypes(EVT_TASK_FAILED, EVT_TASK_FINISHED, EVT_JOB_MAPPED);
-
- final Ignite g = G.start(c);
-
- final GridCache<Long, GridTestEntity> cache = g.cache("local");
-
- Random rnd = new Random();
-
- for (int i = 0; i < MAX_SIZE; i++) {
- if (rnd.nextBoolean())
- cache.put((long)i, new GridTestEntity(Integer.toHexString(rnd.nextInt(MAX_NAMES)), new Date()));
-
- if (i % 10000 == 0)
- System.out.println(i);
- }
-
- List<Runner> rs = F.asList(
- new Runner("put", 1000, getInt(p, "put-threads", 8)) {
- @Override
- protected void doRun(Random rnd) throws Exception {
- cache.put((long)rnd.nextInt(MAX_SIZE), new GridTestEntity(Integer.toHexString(rnd.nextInt(MAX_NAMES)),
- null));
- }
- }.start(),
-
- new Runner("remove", 1000, getInt(p, "remove-threads", 2)) {
- @Override
- protected void doRun(Random rnd) throws Exception {
- cache.remove((long)rnd.nextInt(MAX_SIZE));
- }
- }.start(),
-
- new Runner("query", 10, getInt(p, "query-threads", 8)) {
- @Override
- protected void doRun(Random rnd) throws Exception {
- GridCacheQuery<Map.Entry<Long, GridTestEntity>> qry = cache.queries().createSqlQuery(
- GridTestEntity.class, "name = ?");
-
- qry.execute(Integer.toHexString(rnd.nextInt(MAX_NAMES))).get();
-
-// U.sleep(getInt(p, "query-sleep-time", 25));
- }
- }.start());
-
- for(;;) {
- U.sleep(getInt(p, "print-period", 3000));
-
- for (Runner r : rs)
- r.print();
-
- long bytes = indexing.getAllocatedOffHeapMemory();
-
- System.out.println("offheap bytes: " + bytes);
-
- System.out.println();
- }
- }
-
- /**
- * Runs job in loop.
- */
- private abstract static class Runner implements Runnable {
- /** */
- private final String name;
-
- /** */
- private final int iters;
-
- /** */
- private final int threads;
-
- /** */
- private AtomicLong cntr = new AtomicLong();
-
- /** */
- private long lastPrintTime;
- /**
- * Constructor.
- *
- * @param name Name.
- * @param iters Iterations count to measure.
- * @param threads Threads.
- */
- protected Runner(String name, int iters, int threads) {
- this.name = name;
- this.iters = iters;
- this.threads = threads;
- }
-
- /**
- * Start runner.
- *
- * @return Self.
- */
- Runner start() {
- Thread[] ths = new Thread[threads];
-
- for (int i = 0; i < threads; i++) {
- ths[i] = new Thread(this, name + "-" + i);
-
- ths[i].setDaemon(true);
-
- ths[i].start();
- }
-
- lastPrintTime = System.currentTimeMillis();
-
- return this;
- }
-
- /** */
- @SuppressWarnings("InfiniteLoopStatement")
- @Override public void run() {
- Random rnd = new Random();
-
- try {
- for (;;) {
- for (int i = 0; i < iters; i++)
- doRun(rnd);
-
- cntr.addAndGet(iters);
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Print stats.
- */
- void print() {
- long cnt = cntr.get();
- long time = System.currentTimeMillis();
-
- X.println("-- " + name + ": " + (cnt * 1000 / (time - lastPrintTime)) + " op/sec");
-
- lastPrintTime = time;
-
- cntr.addAndGet(-cnt);
- }
-
- /**
- * Do the job.
- *
- * @param rnd Random for current thread.
- * @throws Exception If failed.
- */
- protected abstract void doRun(Random rnd) throws Exception;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/testsuites/bamboo/GridH2IndexingSpiTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/testsuites/bamboo/GridH2IndexingSpiTestSuite.java b/modules/indexing/src/test/java/org/gridgain/testsuites/bamboo/GridH2IndexingSpiTestSuite.java
index b0aedb6..c1d1b1c 100644
--- a/modules/indexing/src/test/java/org/gridgain/testsuites/bamboo/GridH2IndexingSpiTestSuite.java
+++ b/modules/indexing/src/test/java/org/gridgain/testsuites/bamboo/GridH2IndexingSpiTestSuite.java
@@ -12,8 +12,8 @@ package org.gridgain.testsuites.bamboo;
import junit.framework.*;
import org.gridgain.grid.kernal.processors.cache.*;
import org.gridgain.grid.kernal.processors.cache.distributed.near.*;
-import org.gridgain.grid.spi.indexing.h2.*;
-import org.gridgain.grid.spi.indexing.h2.opt.*;
+import org.gridgain.grid.kernal.processors.query.h2.*;
+import org.gridgain.grid.kernal.processors.query.h2.opt.*;
/**
* H2 indexing SPI tests.
@@ -30,18 +30,16 @@ public class GridH2IndexingSpiTestSuite extends TestSuite {
suite.addTest(new TestSuite(GridH2TableSelfTest.class));
// H2 Indexing in-memory.
- suite.addTest(new TestSuite(GridH2IndexingSpiInMemStartStopSelfTest.class));
- suite.addTest(new TestSuite(GridH2IndexingSpiInMemSelfTest.class));
+ suite.addTest(new TestSuite(GridH2IndexingInMemSelfTest.class));
// H2 Off-heap memory.
- suite.addTest(new TestSuite(GridH2IndexingSpiOffheapStartStopSelfTest.class));
- suite.addTest(new TestSuite(GridH2IndexingSpiOffheapSelfTest.class));
+ suite.addTest(new TestSuite(GridH2IndexingOffheapSelfTest.class));
// Index rebuilding.
suite.addTest(new TestSuite(GridH2IndexRebuildTest.class));
// Geo.
- suite.addTestSuite(GridH2IndexingSpiGeoSelfTest.class);
+ suite.addTestSuite(GridH2IndexingGeoSelfTest.class);
// Tests moved to this suite since they require GridH2IndexingSpi.
suite.addTestSuite(GridCacheOffHeapAndSwapSelfTest.class);
[15/17] incubator-ignite git commit: Merge branch 'master' of
https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-qry
Posted by se...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-qry
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/34115a78
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/34115a78
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/34115a78
Branch: refs/heads/master
Commit: 34115a788357cddbd9afba37f397ff53baf84001
Parents: 2a605d1 a0e5f1b
Author: S.Vladykin <sv...@gridgain.com>
Authored: Wed Dec 10 12:27:26 2014 +0300
Committer: S.Vladykin <sv...@gridgain.com>
Committed: Wed Dec 10 12:27:26 2014 +0300
----------------------------------------------------------------------
.../grid/kernal/visor/VisorMultiNodeTask.java | 31 +++++++---
.../visor/node/VisorNodeDataCollectorJob.java | 64 ++++++++++++++++----
.../visor/node/VisorNodeDataCollectorTask.java | 24 ++++----
3 files changed, 88 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
[13/17] incubator-ignite git commit: Merge branch 'master' of
https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-qry
Posted by se...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-qry
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/59204a51
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/59204a51
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/59204a51
Branch: refs/heads/master
Commit: 59204a517bca1678ebfb06e1aa6267193f08e10b
Parents: 922a2ba 06fbf57
Author: S.Vladykin <sv...@gridgain.com>
Authored: Tue Dec 9 19:32:26 2014 +0300
Committer: S.Vladykin <sv...@gridgain.com>
Committed: Tue Dec 9 19:32:26 2014 +0300
----------------------------------------------------------------------
.../aop/aspectj/GridifyAspectJAspect.java | 2 +-
.../aspectj/GridifySetToSetAspectJAspect.java | 2 +-
.../aspectj/GridifySetToValueAspectJAspect.java | 2 +-
.../test/config/aop/aspectj/META-INF/aop.xml | 4 +-
.../grid/gridify/GridAbstractAopTest.java | 2 +-
.../grid/gridify/GridNonSpringAopSelfTest.java | 2 +-
.../ignite/compute/ComputeJobAfterSend.java | 2 +-
.../compute/ComputeJobBeforeFailover.java | 2 +-
.../compute/ComputeJobContinuationAdapter.java | 2 +-
.../ignite/compute/ComputeLoadBalancer.java | 6 +-
.../org/apache/ignite/compute/ComputeTask.java | 4 +-
.../ignite/compute/ComputeTaskAdapter.java | 2 +-
.../ignite/compute/ComputeTaskSplitAdapter.java | 2 +-
.../ignite/marshaller/IgniteMarshaller.java | 4 +-
.../marshaller/jdk/IgniteJdkMarshaller.java | 4 +-
.../optimized/IgniteOptimizedMarshaller.java | 4 +-
.../IgniteExecutorServiceResource.java | 4 +-
.../ignite/resources/IgniteHomeResource.java | 4 +-
.../resources/IgniteInstanceResource.java | 4 +-
.../resources/IgniteJobContextResource.java | 4 +-
.../resources/IgniteLocalHostResource.java | 4 +-
.../resources/IgniteLocalNodeIdResource.java | 4 +-
.../ignite/resources/IgniteLoggerResource.java | 4 +-
.../resources/IgniteMBeanServerResource.java | 4 +-
.../resources/IgniteMarshallerResource.java | 4 +-
.../ignite/resources/IgniteNameResource.java | 4 +-
.../ignite/resources/IgniteServiceResource.java | 4 +-
.../IgniteSpringApplicationContextResource.java | 4 +-
.../ignite/resources/IgniteSpringResource.java | 4 +-
.../IgniteTaskContinuousMapperResource.java | 4 +-
.../resources/IgniteTaskSessionResource.java | 4 +-
.../ignite/resources/IgniteUserResource.java | 4 +-
.../PriorityQueueCollisionSpi.java | 8 +-
.../spi/loadbalancing/LoadBalancingSpi.java | 6 +-
.../adaptive/AdaptiveLoadBalancingSpi.java | 4 +-
.../roundrobin/RoundRobinLoadBalancingSpi.java | 4 +-
.../WeightedRandomLoadBalancingSpi.java | 4 +-
.../deployment/GridDeploymentClassLoader.java | 4 +-
.../processors/cache/GridCacheAdapter.java | 7 +-
.../processors/cache/GridCacheMvccManager.java | 31 ++-
.../processors/cache/GridCacheTxAdapter.java | 14 +-
.../processors/cache/GridCacheTxHandler.java | 4 +-
.../cache/GridCacheTxLocalAdapter.java | 5 +-
.../processors/cache/GridCacheTxManager.java | 7 +-
.../dht/GridDhtTransactionalCacheAdapter.java | 1 +
.../cache/distributed/dht/GridDhtTxLocal.java | 2 +
.../distributed/dht/GridDhtTxLocalAdapter.java | 5 +-
.../cache/distributed/near/GridNearTxLocal.java | 4 +-
.../processors/cache/local/GridLocalTx.java | 4 +-
.../transactions/IgniteTransactionsImpl.java | 8 +
.../gridgain/grid/kernal/visor/VisorJob.java | 27 +-
.../grid/kernal/visor/VisorMultiNodeTask.java | 51 +++-
.../grid/kernal/visor/VisorOneNodeTask.java | 2 +-
.../grid/kernal/visor/VisorTaskArgument.java | 29 ++-
.../kernal/visor/cache/VisorCacheClearTask.java | 7 +-
.../visor/cache/VisorCacheCompactTask.java | 13 +-
.../kernal/visor/cache/VisorCacheLoadTask.java | 7 +-
.../visor/cache/VisorCacheMetadataTask.java | 7 +-
.../cache/VisorCacheMetricsCollectorTask.java | 9 +-
.../visor/cache/VisorCachePreloadTask.java | 7 +-
.../visor/cache/VisorCacheResetMetricsTask.java | 7 +-
.../visor/cache/VisorCacheSwapBackupsTask.java | 7 +-
.../compute/VisorComputeCancelSessionsTask.java | 9 +-
.../compute/VisorComputeResetMetricsTask.java | 7 +-
.../VisorComputeToggleMonitoringTask.java | 17 +-
.../kernal/visor/debug/VisorThreadDumpTask.java | 7 +-
.../kernal/visor/file/VisorFileBlockTask.java | 7 +-
.../visor/file/VisorLatestTextFilesTask.java | 7 +-
.../kernal/visor/ggfs/VisorGgfsFormatTask.java | 7 +-
.../visor/ggfs/VisorGgfsProfilerClearTask.java | 7 +-
.../visor/ggfs/VisorGgfsProfilerTask.java | 13 +-
.../visor/ggfs/VisorGgfsResetMetricsTask.java | 7 +-
.../visor/ggfs/VisorGgfsSamplingStateTask.java | 7 +-
.../kernal/visor/log/VisorLogSearchTask.java | 12 +-
.../grid/kernal/visor/misc/VisorAckTask.java | 9 +-
.../visor/misc/VisorLatestVersionTask.java | 7 +-
.../visor/misc/VisorResolveHostNameTask.java | 7 +-
.../VisorNodeConfigurationCollectorJob.java | 5 +-
.../VisorNodeConfigurationCollectorTask.java | 2 +-
.../visor/node/VisorNodeDataCollectorJob.java | 5 +-
.../visor/node/VisorNodeDataCollectorTask.java | 4 +-
.../node/VisorNodeEventsCollectorTask.java | 9 +-
.../grid/kernal/visor/node/VisorNodeGcTask.java | 23 +-
.../kernal/visor/node/VisorNodePingTask.java | 16 +-
.../kernal/visor/node/VisorNodeRestartTask.java | 9 +-
.../kernal/visor/node/VisorNodeStopTask.java | 9 +-
.../VisorPortableMetadataCollectorTask.java | 13 +-
.../visor/query/VisorQueryNextPageTask.java | 7 +-
.../grid/kernal/visor/query/VisorQueryTask.java | 7 +-
.../streamer/VisorStreamerMetricsResetTask.java | 7 +-
.../visor/streamer/VisorStreamerResetTask.java | 7 +-
.../grid/kernal/visor/util/VisorTaskUtils.java | 123 +++++++++
.../GridCacheBasicStoreNoBatchAbstractTest.java | 251 -------------------
.../GridCacheNodeFailureAbstractTest.java | 10 +-
...ansformWriteThroughSingleUpdateSelfTest.java | 98 --------
...chePartitionedBasicStoreNoBatchSelfTest.java | 25 --
...acheReplicatedBasicStoreNoBatchSelfTest.java | 25 --
...cheLocalAtomicBasicStoreNoBatchSelfTest.java | 24 --
...GridCacheLocalBasicStoreNoBatchSelfTest.java | 25 --
.../bamboo/GridCacheFailoverTestSuite.java | 3 +
.../bamboo/GridDataGridTestSuite.java | 29 +--
.../cache/jta/GridCacheJtaManager.java | 1 +
.../org/gridgain/scalar/ScalarConversions.scala | 2 +-
.../org/gridgain/scalar/lang/ScalarJob.scala | 2 +-
.../visor/commands/gc/VisorGcCommand.scala | 4 +-
.../main/scala/org/gridgain/visor/visor.scala | 10 +-
106 files changed, 561 insertions(+), 729 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/59204a51/modules/core/src/main/java/org/gridgain/grid/kernal/visor/query/VisorQueryTask.java
----------------------------------------------------------------------
[08/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java
new file mode 100644
index 0000000..3a850cc
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java
@@ -0,0 +1,1998 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+* __ ____/___________(_)______ /__ ____/______ ____(_)_______
+* _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+* / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+* \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+*/
+
+package org.gridgain.grid.kernal.processors.query.h2;
+
+import org.apache.ignite.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.marshaller.*;
+import org.apache.ignite.resources.*;
+import org.apache.ignite.spi.*;
+import org.apache.ignite.spi.indexing.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.kernal.*;
+import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.kernal.processors.query.*;
+import org.gridgain.grid.kernal.processors.query.h2.opt.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.lang.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.h2.api.*;
+import org.h2.command.*;
+import org.h2.constant.*;
+import org.h2.index.*;
+import org.h2.jdbc.*;
+import org.h2.message.*;
+import org.h2.mvstore.cache.*;
+import org.h2.server.web.*;
+import org.h2.table.*;
+import org.h2.tools.*;
+import org.h2.util.*;
+import org.h2.value.*;
+import org.jdk8.backport.*;
+import org.jetbrains.annotations.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.math.*;
+import java.sql.*;
+import java.text.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import static org.apache.ignite.IgniteSystemProperties.*;
+import static org.gridgain.grid.kernal.processors.query.GridQueryIndexType.*;
+import static org.gridgain.grid.kernal.processors.query.h2.opt.GridH2AbstractKeyValueRow.*;
+import static org.h2.result.SortOrder.*;
+
+/**
+ * Indexing implementation based on H2 database engine. In this implementation main query language is SQL,
+ * fulltext indexing can be performed using Lucene. For each registered space
+ * the SPI will create respective schema, for default space (where space name is null) schema
+ * with name {@code PUBLIC} will be used. To avoid name conflicts user should not explicitly name
+ * a schema {@code PUBLIC}.
+ * <p>
+ * For each registered {@link GridQueryTypeDescriptor} this SPI will create respective SQL table with
+ * {@code '_key'} and {@code '_val'} fields for key and value, and fields from
+ * {@link GridQueryTypeDescriptor#keyFields()} and {@link GridQueryTypeDescriptor#valueFields()}.
+ * For each table it will create indexes declared in {@link GridQueryTypeDescriptor#indexes()}.
+ * <h1 class="header">Some important defaults.</h1>
+ * <ul>
+ * <li>All the data will be kept in memory</li>
+ * <li>Primitive types will not be indexed (e.g. java types which can be directly converted to SQL types)</li>
+ * <li>
+ * Key types will be converted to SQL types, so it is impossible to store one value type with
+ * different key types
+ * </li>
+ * </ul>
+ * @see GridIndexingSpi
+ */
+@SuppressWarnings({"UnnecessaryFullyQualifiedName", "NonFinalStaticVariableUsedInClassInitialization"})
+public class GridH2Indexing implements GridQueryIndexing {
+ /** Default DB options. */
+ private static final String DFLT_DB_OPTIONS = ";LOCK_MODE=3;MULTI_THREADED=1;DB_CLOSE_ON_EXIT=FALSE" +
+ ";DEFAULT_LOCK_TIMEOUT=10000";
+
+ /** Options for optimized mode to work properly. */
+ private static final String OPTIMIZED_DB_OPTIONS = ";OPTIMIZE_REUSE_RESULTS=0;QUERY_CACHE_SIZE=0;" +
+ "RECOMPILE_ALWAYS=1;MAX_OPERATION_MEMORY=0";
+
+ /** Field name for key. */
+ public static final String KEY_FIELD_NAME = "_key";
+
+ /** Field name for value. */
+ public static final String VAL_FIELD_NAME = "_val";
+
+ /** */
+ private static final Field COMMAND_FIELD;
+
+ /**
+ * Command in H2 prepared statement.
+ */
+ static {
+ try {
+ COMMAND_FIELD = JdbcPreparedStatement.class.getDeclaredField("command");
+
+ COMMAND_FIELD.setAccessible(true);
+ }
+ catch (NoSuchFieldException e) {
+ throw new IllegalStateException("Check H2 version in classpath.", e);
+ }
+ }
+
+ /** */
+ private static final ThreadLocal<GridH2Indexing> localSpi = new ThreadLocal<>();
+
+ /** */
+ private volatile String cachedSearchPathCmd;
+
+ /** Cache for deserialized offheap rows. */
+ private CacheLongKeyLIRS<GridH2KeyValueRowOffheap> rowCache = new CacheLongKeyLIRS<>(32 * 1024, 1, 128, 256);
+
+ /** Logger. */
+ @IgniteLoggerResource
+ private IgniteLogger log;
+
+ /** Node ID. */
+ @IgniteLocalNodeIdResource
+ private UUID nodeId;
+
+ /** */
+ @IgniteMarshallerResource
+ private IgniteMarshaller marshaller;
+
+ /** */
+ private GridUnsafeMemory offheap;
+
+ /** */
+ private final Collection<String> schemaNames = new GridConcurrentHashSet<>();
+
+ /** Collection of schemaNames and registered tables. */
+ private final ConcurrentMap<String, Schema> schemas = new ConcurrentHashMap8<>();
+
+ /** */
+ private String dbUrl = "jdbc:h2:mem:";
+
+ /** */
+ private final Collection<Connection> conns = Collections.synchronizedCollection(new ArrayList<Connection>());
+
+ /** */
+ private final ThreadLocal<ConnectionWrapper> connCache = new ThreadLocal<ConnectionWrapper>() {
+ @Nullable @Override public ConnectionWrapper get() {
+ ConnectionWrapper c = super.get();
+
+ boolean reconnect = true;
+
+ try {
+ reconnect = c == null || c.connection().isClosed();
+ }
+ catch (SQLException e) {
+ U.warn(log, "Failed to check connection status.", e);
+ }
+
+ if (reconnect) {
+ c = initialValue();
+
+ set(c);
+ }
+
+ return c;
+ }
+
+ @Nullable @Override protected ConnectionWrapper initialValue() {
+ Connection c = null;
+
+ try {
+ c = DriverManager.getConnection(dbUrl);
+
+ String[] searchPath = cfg.getSearchPath();
+
+ if (!F.isEmpty(searchPath)) {
+ try (Statement s = c.createStatement()) {
+ String cmd = cachedSearchPathCmd;
+
+ if (cmd == null) {
+ SB b = new SB("SET SCHEMA_SEARCH_PATH ");
+
+ for (int i = 0; i < searchPath.length; i++) {
+ if (i != 0)
+ b.a(',');
+
+ b.a('"').a(schema(searchPath[i])).a('"');
+ }
+
+ cachedSearchPathCmd = cmd = b.toString();
+ }
+
+ s.executeUpdate(cmd);
+ }
+ }
+
+ conns.add(c);
+
+ return new ConnectionWrapper(c);
+ }
+ catch (SQLException e) {
+ U.close(c, log);
+
+ throw new GridRuntimeException("Failed to initialize DB connection: " + dbUrl, e);
+ }
+ }
+ };
+
+ /** */
+ private volatile GridQueryConfiguration cfg = new GridQueryConfiguration();
+
+ /** */
+ private volatile GridKernalContext ctx;
+
+ /**
+ * Gets DB connection.
+ *
+ * @param schema Whether to set schema for connection or not.
+ * @return DB connection.
+ * @throws GridException In case of error.
+ */
+ private Connection connectionForThread(@Nullable String schema) throws GridException {
+ ConnectionWrapper c = connCache.get();
+
+ if (c == null)
+ throw new GridException("Failed to get DB connection for thread (check log for details).");
+
+ if (schema != null && !F.eq(c.schema(), schema)) {
+ Statement stmt = null;
+
+ try {
+ stmt = c.connection().createStatement();
+
+ stmt.executeUpdate("SET SCHEMA \"" + schema + '"');
+
+ if (log.isDebugEnabled())
+ log.debug("Initialized H2 schema for queries on space: " + schema);
+
+ c.schema(schema);
+ }
+ catch (SQLException e) {
+ throw new GridException("Failed to set schema for DB connection for thread [schema=" +
+ schema + "]", e);
+ }
+ finally {
+ U.close(stmt, log);
+ }
+ }
+
+ return c.connection();
+ }
+
+ /**
+ * Creates DB schema if it has not been created yet.
+ *
+ * @param schema Schema name.
+ * @throws GridException If failed to create db schema.
+ */
+ private void createSchemaIfAbsent(String schema) throws GridException {
+ executeStatement("CREATE SCHEMA IF NOT EXISTS \"" + schema + '"');
+
+ if (log.isDebugEnabled())
+ log.debug("Created H2 schema for index database: " + schema);
+ }
+
+ /**
+ * @param sql SQL statement.
+ * @throws GridException If failed.
+ */
+ private void executeStatement(String sql) throws GridException {
+ Statement stmt = null;
+
+ try {
+ Connection c = connectionForThread(null);
+
+ stmt = c.createStatement();
+
+ stmt.executeUpdate(sql);
+ }
+ catch (SQLException e) {
+ onSqlException();
+
+ throw new GridException("Failed to execute statement: " + sql, e);
+ }
+ finally {
+ U.close(stmt, log);
+ }
+ }
+
+ /**
+ * Removes entry with specified key from any tables (if exist).
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @param tblToUpdate Table to update.
+ * @throws GridException In case of error.
+ */
+ private void removeKey(@Nullable String spaceName, Object key, TableDescriptor tblToUpdate)
+ throws GridException {
+ try {
+ Collection<TableDescriptor> tbls = tables(schema(spaceName));
+
+ if (tbls.size() > 1) {
+ boolean fixedTyping = isIndexFixedTyping(spaceName);
+
+ for (TableDescriptor tbl : tbls) {
+ if (tbl != tblToUpdate && (tbl.type().keyClass().equals(key.getClass()) ||
+ !fixedTyping)) {
+ if (tbl.tbl.update(key, null, 0)) {
+ if (tbl.luceneIdx != null)
+ tbl.luceneIdx.remove(key);
+
+ return;
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e) {
+ throw new GridException("Failed to remove key: " + key, e);
+ }
+ }
+
+ /**
+ * Binds object to prepared statement.
+ *
+ * @param stmt SQL statement.
+ * @param idx Index.
+ * @param obj Value to store.
+ * @throws GridException If failed.
+ */
+ private void bindObject(PreparedStatement stmt, int idx, @Nullable Object obj) throws GridException {
+ try {
+ if (obj == null)
+ stmt.setNull(idx, Types.VARCHAR);
+ else
+ stmt.setObject(idx, obj);
+ }
+ catch (SQLException e) {
+ throw new GridException("Failed to bind parameter [idx=" + idx + ", obj=" + obj + ']', e);
+ }
+ }
+
+ /**
+ * Handles SQL exception.
+ */
+ private void onSqlException() {
+ Connection conn = connCache.get().connection();
+
+ connCache.set(null);
+
+ if (conn != null) {
+ conns.remove(conn);
+
+ // Reset connection to receive new one at next call.
+ U.close(conn, log);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void store(@Nullable String spaceName, GridQueryTypeDescriptor type, Object k, Object v, byte[] ver,
+ long expirationTime) throws GridException {
+ TableDescriptor tbl = tableDescriptor(spaceName, type);
+
+ if (tbl == null)
+ return; // Type was rejected.
+
+ localSpi.set(this);
+
+ try {
+ removeKey(spaceName, k, tbl);
+
+ if (expirationTime == 0)
+ expirationTime = Long.MAX_VALUE;
+
+ tbl.tbl.update(k, v, expirationTime);
+
+ if (tbl.luceneIdx != null)
+ tbl.luceneIdx.store(k, v, ver, expirationTime);
+ }
+ finally {
+ localSpi.remove();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(@Nullable String spaceName, Object key) throws GridException {
+ if (log.isDebugEnabled())
+ log.debug("Removing key from cache query index [locId=" + nodeId + ", key=" + key + ']');
+
+ localSpi.set(this);
+
+ try {
+ for (TableDescriptor tbl : tables(schema(spaceName))) {
+ if (tbl.type().keyClass().equals(key.getClass()) || !isIndexFixedTyping(spaceName)) {
+ if (tbl.tbl.update(key, null, 0)) {
+ if (tbl.luceneIdx != null)
+ tbl.luceneIdx.remove(key);
+
+ return;
+ }
+ }
+ }
+ }
+ finally {
+ localSpi.remove();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onSwap(@Nullable String spaceName, Object key) throws GridException {
+ Schema schema = schemas.get(schema(spaceName));
+
+ if (schema == null)
+ return;
+
+ localSpi.set(this);
+
+ try {
+ for (TableDescriptor tbl : schema.values()) {
+ if (tbl.type().keyClass().equals(key.getClass()) || !isIndexFixedTyping(spaceName)) {
+ try {
+ if (tbl.tbl.onSwap(key))
+ return;
+ }
+ catch (GridException e) {
+ throw new GridException(e);
+ }
+ }
+ }
+ }
+ finally {
+ localSpi.remove();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onUnswap(@Nullable String spaceName, Object key, Object val, byte[] valBytes)
+ throws GridException {
+ localSpi.set(this);
+
+ try {
+ for (TableDescriptor tbl : tables(schema(spaceName))) {
+ if (tbl.type().keyClass().equals(key.getClass()) || !isIndexFixedTyping(spaceName)) {
+ try {
+ if (tbl.tbl.onUnswap(key, val))
+ return;
+ }
+ catch (GridException e) {
+ throw new GridException(e);
+ }
+ }
+ }
+ }
+ finally {
+ localSpi.remove();
+ }
+ }
+
+ /**
+ * Drops table form h2 database and clear all related indexes (h2 text, lucene).
+ *
+ * @param tbl Table to unregister.
+ * @throws GridException If failed to unregister.
+ */
+ private void removeTable(TableDescriptor tbl) throws GridException {
+ assert tbl != null;
+
+ if (log.isDebugEnabled())
+ log.debug("Removing query index table: " + tbl.fullTableName());
+
+ Connection c = connectionForThread(null);
+
+ Statement stmt = null;
+
+ try {
+ // NOTE: there is no method dropIndex() for lucene engine correctly working.
+ // So we have to drop all lucene index.
+ // FullTextLucene.dropAll(c); TODO: GG-4015: fix this
+
+ stmt = c.createStatement();
+
+ String sql = "DROP TABLE IF EXISTS " + tbl.fullTableName();
+
+ if (log.isDebugEnabled())
+ log.debug("Dropping database index table with SQL: " + sql);
+
+ stmt.executeUpdate(sql);
+ }
+ catch (SQLException e) {
+ onSqlException();
+
+ throw new GridException("Failed to drop database index table [type=" + tbl.type().name() +
+ ", table=" + tbl.fullTableName() + "]", e);
+ }
+ finally {
+ U.close(stmt, log);
+ }
+
+ tbl.tbl.close();
+
+ if (tbl.luceneIdx != null)
+ U.closeQuiet(tbl.luceneIdx);
+
+ ConcurrentMap<String, TableDescriptor> tbls = schemas.get(tbl.schema());
+
+ if (!F.isEmpty(tbls))
+ tbls.remove(tbl.name());
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryText(
+ @Nullable String spaceName, String qry, GridQueryTypeDescriptor type,
+ GridIndexingQueryFilter filters) throws GridException {
+ TableDescriptor tbl = tableDescriptor(spaceName, type);
+
+ if (tbl != null && tbl.luceneIdx != null)
+ return tbl.luceneIdx.query(qry, filters);
+
+ return new GridEmptyCloseableIterator<>();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void unregisterType(@Nullable String spaceName, GridQueryTypeDescriptor type)
+ throws GridException {
+ TableDescriptor tbl = tableDescriptor(spaceName, type);
+
+ if (tbl != null)
+ removeTable(tbl);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public <K, V> GridQueryFieldsResult queryFields(@Nullable final String spaceName, final String qry,
+ @Nullable final Collection<Object> params, final GridIndexingQueryFilter filters)
+ throws GridException {
+ localSpi.set(this);
+
+ setFilters(filters);
+
+ try {
+ Connection conn = connectionForThread(schema(spaceName));
+
+ ResultSet rs = executeSqlQueryWithTimer(conn, qry, params);
+
+ List<GridQueryFieldMetadata> meta = null;
+
+ if (rs != null) {
+ try {
+ ResultSetMetaData rsMeta = rs.getMetaData();
+
+ meta = new ArrayList<>(rsMeta.getColumnCount());
+
+ for (int i = 1; i <= rsMeta.getColumnCount(); i++) {
+ String schemaName = rsMeta.getSchemaName(i);
+ String typeName = rsMeta.getTableName(i);
+ String name = rsMeta.getColumnLabel(i);
+ String type = rsMeta.getColumnClassName(i);
+
+ meta.add(new SqlFieldMetadata(schemaName, typeName, name, type));
+ }
+ }
+ catch (SQLException e) {
+ throw new IgniteSpiException("Failed to get meta data.", e);
+ }
+ }
+
+ return new GridQueryFieldsResultAdapter(meta, new FieldsIterator(rs));
+ }
+ finally {
+ setFilters(null);
+
+ localSpi.remove();
+ }
+ }
+
+ /**
+ * @param stmt Prepared statement.
+ * @return Command type.
+ */
+ private static int commandType(PreparedStatement stmt) {
+ try {
+ return ((CommandInterface)COMMAND_FIELD.get(stmt)).getCommandType();
+ }
+ catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * @return Configuration.
+ */
+ public GridQueryConfiguration configuration() {
+ return cfg;
+ }
+
+ /**
+ * Executes sql query.
+ *
+ * @param conn Connection,.
+ * @param sql Sql query.
+ * @param params Parameters.
+ * @return Result.
+ * @throws GridException If failed.
+ */
+ @Nullable private ResultSet executeSqlQuery(Connection conn, String sql,
+ @Nullable Collection<Object> params) throws GridException {
+ PreparedStatement stmt;
+
+ try {
+ stmt = conn.prepareStatement(sql);
+ }
+ catch (SQLException e) {
+ if (e.getErrorCode() == ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1)
+ return null;
+
+ throw new GridException("Failed to parse SQL query: " + sql, e);
+ }
+
+ switch (commandType(stmt)) {
+ case CommandInterface.SELECT:
+ case CommandInterface.CALL:
+ case CommandInterface.EXPLAIN:
+ case CommandInterface.ANALYZE:
+ break;
+ default:
+ throw new GridException("Failed to execute non-query SQL statement: " + sql);
+ }
+
+ bindParameters(stmt, params);
+
+ try {
+ return stmt.executeQuery();
+ }
+ catch (SQLException e) {
+ throw new GridException("Failed to execute SQL query.", e);
+ }
+ }
+
+ /**
+ * Executes sql query and prints warning if query is too slow..
+ *
+ * @param conn Connection,.
+ * @param sql Sql query.
+ * @param params Parameters.
+ * @return Result.
+ * @throws GridException If failed.
+ */
+ private ResultSet executeSqlQueryWithTimer(Connection conn, String sql,
+ @Nullable Collection<Object> params) throws GridException {
+ long start = U.currentTimeMillis();
+
+ try {
+ ResultSet rs = executeSqlQuery(conn, sql, params);
+
+ long time = U.currentTimeMillis() - start;
+
+ long longQryExecTimeout = cfg.getLongQueryExecutionTimeout();
+
+ if (time > longQryExecTimeout) {
+ String msg = "Query execution is too long (" + time + " ms): " + sql;
+
+ String longMsg = msg;
+
+ if (cfg.isLongQueryExplain()) {
+ ResultSet plan = executeSqlQuery(conn, "EXPLAIN " + sql, params);
+
+ if (plan == null)
+ longMsg = "Failed to explain plan because required table does not exist: " + sql;
+ else {
+ plan.next();
+
+ // Add SQL explain result message into log.
+ longMsg = "Query execution is too long [time=" + time + " ms, sql='" + sql + '\'' +
+ ", plan=" + U.nl() + plan.getString(1) + U.nl() + ", parameters=" + params + "]";
+ }
+ }
+
+ LT.warn(log, null, longMsg, msg);
+ }
+
+ return rs;
+ }
+ catch (SQLException e) {
+ onSqlException();
+
+ throw new GridException(e);
+ }
+ }
+
+ /**
+ * Executes query.
+ *
+ * @param qry Query.
+ * @param params Query parameters.
+ * @param tbl Target table of query to generate select.
+ * @return Result set.
+ * @throws GridException If failed.
+ */
+ private ResultSet executeQuery(String qry, @Nullable Collection<Object> params,
+ @Nullable TableDescriptor tbl) throws GridException {
+ Connection conn = connectionForThread(tbl != null ? tbl.schema() : "PUBLIC");
+
+ String sql = generateQuery(qry, tbl);
+
+ return executeSqlQueryWithTimer(conn, sql, params);
+ }
+
+ /**
+ * Binds parameters to prepared statement.
+ *
+ * @param stmt Prepared statement.
+ * @param params Parameters collection.
+ * @throws GridException If failed.
+ */
+ private void bindParameters(PreparedStatement stmt, @Nullable Collection<Object> params) throws GridException {
+ if (!F.isEmpty(params)) {
+ int idx = 1;
+
+ for (Object arg : params)
+ bindObject(stmt, idx++, arg);
+ }
+ }
+
+ /**
+ * Executes regular query.
+ * Note that SQL query can not refer to table alias, so use full table name instead.
+ *
+ * @param spaceName Space name.
+ * @param qry Query.
+ * @param params Query parameters.
+ * @param type Query return type.
+ * @param filters Space name and key filters.
+ * @return Queried rows.
+ * @throws GridException If failed.
+ */
+ @SuppressWarnings("unchecked")
+ @Override public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> query(@Nullable String spaceName,
+ final String qry, @Nullable final Collection<Object> params, GridQueryTypeDescriptor type,
+ final GridIndexingQueryFilter filters) throws GridException {
+ final TableDescriptor tbl = tableDescriptor(spaceName, type);
+
+ if (tbl == null)
+ return new GridEmptyCloseableIterator<>();
+
+ setFilters(filters);
+
+ localSpi.set(this);
+
+ try {
+ ResultSet rs = executeQuery(qry, params, tbl);
+
+ return new KeyValIterator(rs);
+ }
+ finally {
+ setFilters(null);
+
+ localSpi.remove();
+ }
+ }
+
+ /**
+ * Sets filters for current thread. Must be set to not null value
+ * before executeQuery and reset to null after in finally block since it signals
+ * to table that it should return content without expired values.
+ *
+ * @param filters Filters.
+ */
+ private void setFilters(@Nullable GridIndexingQueryFilter filters) {
+ GridH2IndexBase.setFiltersForThread(filters);
+ }
+
+ /**
+ * Prepares statement for query.
+ *
+ * @param qry Query string.
+ * @param tbl Table to use.
+ * @return Prepared statement.
+ * @throws GridException In case of error.
+ */
+ private String generateQuery(String qry, @Nullable TableDescriptor tbl) throws GridException {
+ boolean needSelect = tbl != null;
+
+ String str = qry.trim().toUpperCase();
+
+ if (!str.startsWith("FROM")) {
+ if (str.startsWith("SELECT")) {
+ if (needSelect) {
+ StringTokenizer st = new StringTokenizer(str, " ");
+
+ String errMsg = "Wrong query format, query must start with 'select * from' " +
+ "or 'from' or without such keywords.";
+
+ if (st.countTokens() > 3) {
+ st.nextToken();
+ String wildcard = st.nextToken();
+ String from = st.nextToken();
+
+ if (!"*".equals(wildcard) || !"FROM".equals(from))
+ throw new GridException(errMsg);
+
+ needSelect = false;
+ }
+ else
+ throw new GridException(errMsg);
+ }
+ }
+ else {
+ boolean needWhere = !str.startsWith("ORDER") && !str.startsWith("LIMIT");
+
+ qry = needWhere ? "FROM " + tbl.fullTableName() + " WHERE " + qry :
+ "FROM " + tbl.fullTableName() + ' ' + qry;
+ }
+ }
+
+ GridStringBuilder ptrn = new SB("SELECT {0}.").a(KEY_FIELD_NAME);
+
+ ptrn.a(", {0}.").a(VAL_FIELD_NAME);
+
+ return needSelect ? MessageFormat.format(ptrn.toString(), tbl.fullTableName()) + ' ' + qry : qry;
+ }
+
+ /**
+ * Registers new class description.
+ *
+ * This implementation doesn't support type reregistration.
+ *
+ * @param type Type description.
+ * @throws GridException In case of error.
+ */
+ @Override public boolean registerType(@Nullable String spaceName, GridQueryTypeDescriptor type)
+ throws GridException {
+ if (!validateTypeDescriptor(spaceName, type))
+ return false;
+
+ for (TableDescriptor table : tables(schema(spaceName)))
+ // Need to compare class names rather than classes to define
+ // whether a class was previously undeployed.
+ if (table.type().valueClass().getClass().getName().equals(type.valueClass().getName()))
+ throw new GridException("Failed to register type in query index because" +
+ " class is already registered (most likely that class with the same name" +
+ " was not properly undeployed): " + type);
+
+ TableDescriptor tbl = new TableDescriptor(spaceName, type);
+
+ try {
+ Connection conn = connectionForThread(null);
+
+ Schema schema = schemas.get(tbl.schema());
+
+ if (schema == null) {
+ schema = new Schema(spaceName);
+
+ Schema existing = schemas.putIfAbsent(tbl.schema(), schema);
+
+ if (existing != null)
+ schema = existing;
+ }
+
+ createTable(schema, tbl, conn);
+
+ schema.put(tbl.name(), tbl);
+ }
+ catch (SQLException e) {
+ onSqlException();
+
+ throw new GridException("Failed to register query type: " + type, e);
+ }
+
+ return true;
+ }
+
+ /**
+ * @param cls Class.
+ * @return True if given class has primitive respective sql type.
+ */
+ private boolean isPrimitive(Class<?> cls) {
+ DBTypeEnum valType = DBTypeEnum.fromClass(cls);
+
+ return valType != DBTypeEnum.BINARY && valType != DBTypeEnum.OTHER &&
+ valType != DBTypeEnum.ARRAY;
+ }
+
+ /**
+ * Validates properties described by query types.
+ *
+ * @param spaceName Space name.
+ * @param type Type descriptor.
+ * @return True if type is valid.
+ * @throws GridException If validation failed.
+ */
+ private boolean validateTypeDescriptor(@Nullable String spaceName, GridQueryTypeDescriptor type)
+ throws GridException {
+ assert type != null;
+
+ boolean keyPrimitive = isPrimitive(type.keyClass());
+ boolean valPrimitive = isPrimitive(type.valueClass());
+
+ // Do not register if value is not primitive and
+ // there are no indexes or fields defined.
+ if (!type.valueTextIndex() && type.indexes().isEmpty() &&
+ type.keyFields().isEmpty() && type.valueFields().isEmpty())
+ return keyPrimitive && isIndexPrimitiveKey(spaceName) || valPrimitive && isIndexPrimitiveValue(spaceName);
+
+ Collection<String> names = new HashSet<>();
+
+ names.addAll(type.keyFields().keySet());
+ names.addAll(type.valueFields().keySet());
+
+ if (names.size() < type.keyFields().size() + type.valueFields().size())
+ throw new GridException("Found duplicated properties with the same name [keyType=" +
+ type.keyClass().getName() + ", valueType=" + type.valueClass().getName() + "]");
+
+ String ptrn = "Name ''{0}'' is reserved and cannot be used as a field name [class=" + type + "]";
+
+ for (String name : names) {
+ if (name.equals(KEY_FIELD_NAME) || name.equals(VAL_FIELD_NAME))
+ throw new GridException(MessageFormat.format(ptrn, name));
+ }
+
+ return true;
+ }
+
+ /**
+ * Escapes name to be valid SQL identifier. Currently just replaces '.' and '$' sign with '_'.
+ *
+ * @param name Name.
+ * @param escapeAll Escape flag.
+ * @return Escaped name.
+ */
+ private static String escapeName(String name, boolean escapeAll) {
+ if (escapeAll)
+ return "\"" + name + "\"";
+
+ SB sb = null;
+
+ for (int i = 0; i < name.length(); i++) {
+ char ch = name.charAt(i);
+
+ if (!Character.isLetter(ch) && !Character.isDigit(ch) && ch != '_' &&
+ !(ch == '"' && (i == 0 || i == name.length() - 1)) && ch != '-') {
+ // Class name can also contain '$' or '.' - these should be escaped.
+ assert ch == '$' || ch == '.';
+
+ if (sb == null)
+ sb = new SB();
+
+ sb.a(name.substring(sb.length(), i));
+
+ // Replace illegal chars with '_'.
+ sb.a('_');
+ }
+ }
+
+ if (sb == null)
+ return name;
+
+ sb.a(name.substring(sb.length(), name.length()));
+
+ return sb.toString();
+ }
+
+ /**
+ * Create db table by using given table descriptor.
+ *
+ * @param schema Schema.
+ * @param tbl Table descriptor.
+ * @param conn Connection.
+ * @throws SQLException If failed to create db table.
+ */
+ private void createTable(Schema schema, TableDescriptor tbl, Connection conn) throws SQLException {
+ assert tbl != null;
+
+ boolean keyAsObj = !isIndexFixedTyping(schema.spaceName);
+
+ boolean escapeAll = isEscapeAll(schema.spaceName);
+
+ String keyType = keyAsObj ? "OTHER" : dbTypeFromClass(tbl.type().keyClass());
+ String valTypeStr = dbTypeFromClass(tbl.type().valueClass());
+
+ SB sql = new SB();
+
+ sql.a("CREATE TABLE ").a(tbl.fullTableName()).a(" (")
+ .a(KEY_FIELD_NAME).a(' ').a(keyType).a(" NOT NULL");
+
+ sql.a(',').a(VAL_FIELD_NAME).a(' ').a(valTypeStr);
+
+ for (Map.Entry<String, Class<?>> e: tbl.type().keyFields().entrySet())
+ sql.a(',').a(escapeName(e.getKey(), escapeAll)).a(' ').a(dbTypeFromClass(e.getValue()));
+
+ for (Map.Entry<String, Class<?>> e: tbl.type().valueFields().entrySet())
+ sql.a(',').a(escapeName(e.getKey(), escapeAll)).a(' ').a(dbTypeFromClass(e.getValue()));
+
+ sql.a(')');
+
+ if (log.isDebugEnabled())
+ log.debug("Creating DB table with SQL: " + sql);
+
+ GridH2RowDescriptor desc = new RowDescriptor(tbl.type(), schema, keyAsObj);
+
+ GridH2Table.Engine.createTable(conn, sql.toString(), desc, tbl, tbl.spaceName);
+ }
+
+ /**
+ * Gets corresponding DB type from java class.
+ *
+ * @param cls Java class.
+ * @return DB type name.
+ */
+ private String dbTypeFromClass(Class<?> cls) {
+ return DBTypeEnum.fromClass(cls).dBTypeAsString();
+ }
+
+ /**
+ * Gets table descriptor by value type.
+ *
+ * @param spaceName Space name.
+ * @param type Value type descriptor.
+ * @return Table descriptor or {@code null} if not found.
+ */
+ @Nullable private TableDescriptor tableDescriptor(@Nullable String spaceName, GridQueryTypeDescriptor type) {
+ return tableDescriptor(type.name(), spaceName);
+ }
+
+ /**
+ * Gets table descriptor by type and space names.
+ *
+ * @param type Type name.
+ * @param space Space name.
+ * @return Table descriptor.
+ */
+ @Nullable private TableDescriptor tableDescriptor(String type, @Nullable String space) {
+ ConcurrentMap<String, TableDescriptor> tbls = schemas.get(schema(space));
+
+ if (tbls == null)
+ return null;
+
+ return tbls.get(type);
+ }
+
+ /**
+ * Gets collection of table for given schema name.
+ *
+ * @param schema Schema name.
+ * @return Collection of table descriptors.
+ */
+ private Collection<TableDescriptor> tables(String schema) {
+ ConcurrentMap<String, TableDescriptor> tbls = schemas.get(schema);
+
+ if (tbls == null)
+ return Collections.emptySet();
+
+ return tbls.values();
+ }
+
+ /**
+ * Gets database schema from space.
+ *
+ * @param space Space name.
+ * @return Schema name.
+ */
+ private static String schema(@Nullable String space) {
+ if (F.isEmpty(space))
+ return "PUBLIC";
+
+ return space;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void rebuildIndexes(@Nullable String spaceName, GridQueryTypeDescriptor type) {
+ if (offheap != null)
+ throw new UnsupportedOperationException("Index rebuilding is not supported when off-heap memory is used");
+
+ TableDescriptor tbl = tableDescriptor(spaceName, type);
+
+ if (tbl == null)
+ return;
+
+ tbl.tbl.rebuildIndexes();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long size(@Nullable String spaceName, GridQueryTypeDescriptor type,
+ GridIndexingQueryFilter filters) throws GridException {
+ TableDescriptor tbl = tableDescriptor(spaceName, type);
+
+ if (tbl == null)
+ return -1;
+
+ IgniteSpiCloseableIterator<List<?>> iter = queryFields(spaceName,
+ "SELECT COUNT(*) FROM " + tbl.fullTableName(), null, null).iterator();
+
+ return ((Number)iter.next().get(0)).longValue();
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("NonThreadSafeLazyInitialization")
+ @Override public void start(GridKernalContext ctx) throws GridException {
+ if (log.isDebugEnabled())
+ log.debug("Starting cache query index...");
+
+ if (ctx != null) { // This is allowed in some tests.
+ this.ctx = ctx;
+
+ GridQueryConfiguration cfg0 = ctx.config().getQueryConfiguration();
+
+ if (cfg0 != null)
+ cfg = cfg0;
+
+ for (GridCacheConfiguration cacheCfg : ctx.config().getCacheConfiguration())
+ registerSpace(cacheCfg.getName());
+ }
+
+ System.setProperty("h2.serializeJavaObject", "false");
+
+ if (SysProperties.serializeJavaObject) {
+ U.warn(log, "Serialization of Java objects in H2 was enabled.");
+
+ SysProperties.serializeJavaObject = false;
+ }
+
+ if (cfg.isUseOptimizedSerializer())
+ Utils.serializer = h2Serializer();
+
+ long maxOffHeapMemory = cfg.getMaxOffHeapMemory();
+
+ if (maxOffHeapMemory != -1) {
+ assert maxOffHeapMemory >= 0 : maxOffHeapMemory;
+
+ offheap = new GridUnsafeMemory(maxOffHeapMemory);
+ }
+
+ SB opt = new SB();
+
+ opt.a(DFLT_DB_OPTIONS).a(OPTIMIZED_DB_OPTIONS);
+
+ String dbName = UUID.randomUUID().toString();
+
+ dbUrl = "jdbc:h2:mem:" + dbName + opt;
+
+ try {
+ Class.forName("org.h2.Driver");
+ }
+ catch (ClassNotFoundException e) {
+ throw new GridException("Failed to find org.h2.Driver class", e);
+ }
+
+ for (String schema : schemaNames)
+ createSchemaIfAbsent(schema);
+
+ try {
+ createSqlFunctions();
+ runInitScript();
+
+ if (getString(GG_H2_DEBUG_CONSOLE) != null) {
+ Connection c = DriverManager.getConnection(dbUrl);
+
+ WebServer webSrv = new WebServer();
+ Server web = new Server(webSrv, "-webPort", "0");
+ web.start();
+ String url = webSrv.addSession(c);
+
+ try {
+ Server.openBrowser(url);
+ }
+ catch (Exception e) {
+ U.warn(log, "Failed to open browser: " + e.getMessage());
+ }
+ }
+ }
+ catch (SQLException e) {
+ throw new GridException(e);
+ }
+
+// registerMBean(gridName, this, GridH2IndexingSpiMBean.class); TODO
+ }
+
+ /**
+ * @return Serializer.
+ */
+ protected JavaObjectSerializer h2Serializer() {
+ return new JavaObjectSerializer() {
+ @Override public byte[] serialize(Object obj) throws Exception {
+ return marshaller.marshal(obj);
+ }
+
+ @Override public Object deserialize(byte[] bytes) throws Exception {
+ return marshaller.unmarshal(bytes, null);
+ }
+ };
+ }
+
+ /**
+ * Runs initial script.
+ *
+ * @throws GridException If failed.
+ * @throws SQLException If failed.
+ */
+ private void runInitScript() throws GridException, SQLException {
+ String initScriptPath = cfg.getInitialScriptPath();
+
+ if (initScriptPath == null)
+ return;
+
+ try (PreparedStatement p = connectionForThread(null).prepareStatement("RUNSCRIPT FROM ? CHARSET 'UTF-8'")) {
+ p.setString(1, initScriptPath);
+
+ p.execute();
+ }
+ }
+
+ /**
+ * Registers SQL functions.
+ *
+ * @throws SQLException If failed.
+ * @throws GridException If failed.
+ */
+ private void createSqlFunctions() throws SQLException, GridException {
+ Class<?>[] idxCustomFuncClss = cfg.getIndexCustomFunctionClasses();
+
+ if (F.isEmpty(idxCustomFuncClss))
+ return;
+
+ for (Class<?> cls : idxCustomFuncClss) {
+ for (Method m : cls.getDeclaredMethods()) {
+ GridCacheQuerySqlFunction ann = m.getAnnotation(GridCacheQuerySqlFunction.class);
+
+ if (ann != null) {
+ int modifiers = m.getModifiers();
+
+ if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers))
+ throw new GridException("Method " + m.getName() + " must be public static.");
+
+ String alias = ann.alias().isEmpty() ? m.getName() : ann.alias();
+
+ String clause = "CREATE ALIAS " + alias + (ann.deterministic() ? " DETERMINISTIC FOR \"" :
+ " FOR \"") + cls.getName() + '.' + m.getName() + '"';
+
+ Collection<String> schemas = new ArrayList<>(schemaNames);
+
+ if (!schemaNames.contains(schema(null)))
+ schemas.add(schema(null));
+
+ for (String schema : schemas) {
+ Connection c = connectionForThread(schema);
+
+ Statement s = c.createStatement();
+
+ s.execute(clause);
+
+ s.close();
+ }
+ }
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws GridException {
+ if (log.isDebugEnabled())
+ log.debug("Stopping cache query index...");
+
+// unregisterMBean(); TODO
+
+ Connection conn = connectionForThread(null);
+
+ for (ConcurrentMap<String, TableDescriptor> m : schemas.values()) {
+ for (TableDescriptor desc : m.values()) {
+ desc.tbl.close();
+
+ if (desc.luceneIdx != null)
+ U.closeQuiet(desc.luceneIdx);
+ }
+ }
+
+ if (conn != null) {
+ Statement stmt = null;
+
+ try {
+ stmt = conn.createStatement();
+
+ stmt.execute("DROP ALL OBJECTS DELETE FILES");
+ stmt.execute("SHUTDOWN");
+ }
+ catch (SQLException e) {
+ throw new GridException("Failed to shutdown database.", e);
+ }
+ finally {
+ U.close(stmt, log);
+ }
+ }
+
+ for (Connection c : conns)
+ U.close(c, log);
+
+ conns.clear();
+ schemas.clear();
+ rowCache.clear();
+
+ if (log.isDebugEnabled())
+ log.debug("Cache query index stopped.");
+ }
+
+ /**
+ * @param spaceName Space name.
+ * @return {@code true} If primitive keys must be indexed.
+ */
+ public boolean isIndexPrimitiveKey(@Nullable String spaceName) {
+ GridCacheQueryConfiguration cfg = cacheQueryConfiguration(spaceName);
+
+ return cfg != null && cfg.isIndexPrimitiveKey();
+ }
+
+ /**
+ * @param spaceName Space name.
+ * @return {@code true} If primitive values must be indexed.
+ */
+ public boolean isIndexPrimitiveValue(String spaceName) {
+ GridCacheQueryConfiguration cfg = cacheQueryConfiguration(spaceName);
+
+ return cfg != null && cfg.isIndexPrimitiveValue();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isIndexFixedTyping(String spaceName) {
+ GridCacheQueryConfiguration cfg = cacheQueryConfiguration(spaceName);
+
+ return cfg != null && cfg.isIndexFixedTyping();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isEscapeAll(String spaceName) {
+ GridCacheQueryConfiguration cfg = cacheQueryConfiguration(spaceName);
+
+ return cfg != null && cfg.isEscapeAll();
+ }
+
+ /**
+ * @param spaceName Space name.
+ * @return Cache query configuration.
+ */
+ @Nullable private GridCacheQueryConfiguration cacheQueryConfiguration(String spaceName) {
+ return ctx == null ? null : ctx.cache().internalCache(spaceName).configuration().getQueryConfiguration();
+ }
+
+ /** {@inheritDoc} */
+ public int getMaxOffheapRowsCacheSize() {
+ return (int)rowCache.getMaxMemory();
+ }
+
+ /** {@inheritDoc} */
+ public int getOffheapRowsCacheSize() {
+ return (int)rowCache.getUsedMemory();
+ }
+
+ /** {@inheritDoc} */
+ public long getAllocatedOffHeapMemory() {
+ return offheap == null ? -1 : offheap.allocatedSize();
+ }
+
+ /**
+ * @param spaceName Space name.
+ */
+ public void registerSpace(String spaceName) {
+ schemaNames.add(schema(spaceName));
+ }
+
+ /**
+ * Wrapper to store connection and flag is schema set or not.
+ */
+ private static class ConnectionWrapper {
+ /** */
+ private Connection conn;
+
+ /** */
+ private volatile String schema;
+
+ /**
+ * @param conn Connection to use.
+ */
+ ConnectionWrapper(Connection conn) {
+ this.conn = conn;
+ }
+
+ /**
+ * @return Schema name if schema is set, null otherwise.
+ */
+ public String schema() {
+ return schema;
+ }
+
+ /**
+ * @param schema Schema name set on this connection.
+ */
+ public void schema(@Nullable String schema) {
+ this.schema = schema;
+ }
+
+ /**
+ * @return Connection.
+ */
+ public Connection connection() {
+ return conn;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(ConnectionWrapper.class, this);
+ }
+ }
+
+ /**
+ * Enum that helps to map java types to database types.
+ */
+ private enum DBTypeEnum {
+ /** */
+ INT("INT"),
+
+ /** */
+ BOOL("BOOL"),
+
+ /** */
+ TINYINT("TINYINT"),
+
+ /** */
+ SMALLINT("SMALLINT"),
+
+ /** */
+ BIGINT("BIGINT"),
+
+ /** */
+ DECIMAL("DECIMAL"),
+
+ /** */
+ DOUBLE("DOUBLE"),
+
+ /** */
+ REAL("REAL"),
+
+ /** */
+ TIME("TIME"),
+
+ /** */
+ TIMESTAMP("TIMESTAMP"),
+
+ /** */
+ DATE("DATE"),
+
+ /** */
+ VARCHAR("VARCHAR"),
+
+ /** */
+ CHAR("CHAR"),
+
+ /** */
+ BINARY("BINARY"),
+
+ /** */
+ UUID("UUID"),
+
+ /** */
+ ARRAY("ARRAY"),
+
+ /** */
+ GEOMETRY("GEOMETRY"),
+
+ /** */
+ OTHER("OTHER");
+
+ /** Map of Class to enum. */
+ private static final Map<Class<?>, DBTypeEnum> map = new HashMap<>();
+
+ /**
+ * Initialize map of DB types.
+ */
+ static {
+ map.put(int.class, INT);
+ map.put(Integer.class, INT);
+ map.put(boolean.class, BOOL);
+ map.put(Boolean.class, BOOL);
+ map.put(byte.class, TINYINT);
+ map.put(Byte.class, TINYINT);
+ map.put(short.class, SMALLINT);
+ map.put(Short.class, SMALLINT);
+ map.put(long.class, BIGINT);
+ map.put(Long.class, BIGINT);
+ map.put(BigDecimal.class, DECIMAL);
+ map.put(double.class, DOUBLE);
+ map.put(Double.class, DOUBLE);
+ map.put(float.class, REAL);
+ map.put(Float.class, REAL);
+ map.put(Time.class, TIME);
+ map.put(Timestamp.class, TIMESTAMP);
+ map.put(java.util.Date.class, TIMESTAMP);
+ map.put(java.sql.Date.class, DATE);
+ map.put(char.class, CHAR);
+ map.put(Character.class, CHAR);
+ map.put(String.class, VARCHAR);
+ map.put(UUID.class, UUID);
+ map.put(byte[].class, BINARY);
+ }
+
+ /** */
+ private final String dbType;
+
+ /**
+ * Constructs new instance.
+ *
+ * @param dbType DB type name.
+ */
+ DBTypeEnum(String dbType) {
+ this.dbType = dbType;
+ }
+
+ /**
+ * Resolves enum by class.
+ *
+ * @param cls Class.
+ * @return Enum value.
+ */
+ public static DBTypeEnum fromClass(Class<?> cls) {
+ DBTypeEnum res = map.get(cls);
+
+ if (res != null)
+ return res;
+
+ if (DataType.isGeometryClass(cls))
+ return GEOMETRY;
+
+ return cls.isArray() && !cls.getComponentType().isPrimitive() ? ARRAY : OTHER;
+ }
+
+ /**
+ * Gets DB type name.
+ *
+ * @return DB type name.
+ */
+ public String dBTypeAsString() {
+ return dbType;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(DBTypeEnum.class, this);
+ }
+ }
+
+ /**
+ * Information about table in database.
+ */
+ private class TableDescriptor implements GridH2Table.IndexesFactory {
+ /** */
+ private final String fullTblName;
+
+ /** */
+ private final GridQueryTypeDescriptor type;
+
+ /** */
+ private final String spaceName;
+
+ /** */
+ private final String schema;
+
+ /** */
+ private GridH2Table tbl;
+
+ /** */
+ private GridLuceneIndex luceneIdx;
+
+ /**
+ * @param spaceName Space name.
+ * @param type Type descriptor.
+ */
+ TableDescriptor(@Nullable String spaceName, GridQueryTypeDescriptor type) {
+ this.spaceName = spaceName;
+ this.type = type;
+
+ schema = GridH2Indexing.schema(spaceName);
+
+ fullTblName = '\"' + schema + "\"." + escapeName(type.name(), isEscapeAll(spaceName));
+ }
+
+ /**
+ * @return Schema name.
+ */
+ public String schema() {
+ return schema;
+ }
+
+ /**
+ * @return Database table name.
+ */
+ String fullTableName() {
+ return fullTblName;
+ }
+
+ /**
+ * @return Database table name.
+ */
+ String name() {
+ return type.name();
+ }
+
+ /**
+ * @return Type.
+ */
+ GridQueryTypeDescriptor type() {
+ return type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TableDescriptor.class, this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public ArrayList<Index> createIndexes(GridH2Table tbl) {
+ this.tbl = tbl;
+
+ ArrayList<Index> idxs = new ArrayList<>();
+
+ idxs.add(new GridH2TreeIndex("_key_PK", tbl, true, KEY_COL, VAL_COL, tbl.indexColumn(0, ASCENDING)));
+
+ if (type().valueClass() == String.class) {
+ try {
+ luceneIdx = new GridLuceneIndex(marshaller, offheap, spaceName, type, true);
+ }
+ catch (GridException e1) {
+ throw new GridRuntimeException(e1);
+ }
+ }
+
+ for (Map.Entry<String, GridQueryIndexDescriptor> e : type.indexes().entrySet()) {
+ String name = e.getKey();
+ GridQueryIndexDescriptor idx = e.getValue();
+
+ if (idx.type() == FULLTEXT) {
+ try {
+ luceneIdx = new GridLuceneIndex(marshaller, offheap, spaceName, type, true);
+ }
+ catch (GridException e1) {
+ throw new GridRuntimeException(e1);
+ }
+ }
+ else {
+ IndexColumn[] cols = new IndexColumn[idx.fields().size()];
+
+ int i = 0;
+
+ boolean escapeAll = isEscapeAll(spaceName);
+
+ for (String field : idx.fields()) {
+ // H2 reserved keywords used as column name is case sensitive.
+ String fieldName = escapeAll ? field : escapeName(field, escapeAll).toUpperCase();
+
+ Column col = tbl.getColumn(fieldName);
+
+ cols[i++] = tbl.indexColumn(col.getColumnId(), idx.descending(field) ? DESCENDING : ASCENDING);
+ }
+
+ if (idx.type() == SORTED)
+ idxs.add(new GridH2TreeIndex(name, tbl, false, KEY_COL, VAL_COL, cols));
+ else if (idx.type() == GEO_SPATIAL)
+ idxs.add(new GridH2SpatialIndex(tbl, name, cols, KEY_COL, VAL_COL));
+ else
+ throw new IllegalStateException();
+ }
+ }
+
+ return idxs;
+ }
+ }
+
+ /**
+ * Special field set iterator based on database result set.
+ */
+ private static class FieldsIterator extends GridH2ResultSetIterator<List<?>> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * @param data Data.
+ * @throws GridException If failed.
+ */
+ protected FieldsIterator(ResultSet data) throws GridException {
+ super(data);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected List<?> createRow() {
+ ArrayList<Object> res = new ArrayList<>(row.length);
+
+ Collections.addAll(res, row);
+
+ return res;
+ }
+ }
+
+ /**
+ * Special key/value iterator based on database result set.
+ */
+ private static class KeyValIterator<K, V> extends GridH2ResultSetIterator<IgniteBiTuple<K, V>> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * @param data Data array.
+ * @throws GridException If failed.
+ */
+ protected KeyValIterator(ResultSet data) throws GridException {
+ super(data);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteBiTuple<K, V> createRow() {
+ K key = (K)row[0];
+ V val = (V)row[1];
+
+ return new IgniteBiTuple<>(key, val);
+ }
+ }
+
+ /**
+ * Field descriptor.
+ */
+ private static class SqlFieldMetadata implements GridQueryFieldMetadata {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Schema name. */
+ private String schemaName;
+
+ /** Type name. */
+ private String typeName;
+
+ /** Name. */
+ private String name;
+
+ /** Type. */
+ private String type;
+
+ /**
+ * Required by {@link Externalizable}.
+ */
+ public SqlFieldMetadata() {
+ // No-op
+ }
+
+ /**
+ * @param schemaName Schema name.
+ * @param typeName Type name.
+ * @param name Name.
+ * @param type Type.
+ */
+ SqlFieldMetadata(@Nullable String schemaName, @Nullable String typeName, String name, String type) {
+ assert name != null;
+ assert type != null;
+
+ this.schemaName = schemaName;
+ this.typeName = typeName;
+ this.name = name;
+ this.type = type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String schemaName() {
+ return schemaName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String typeName() {
+ return typeName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String fieldName() {
+ return name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String fieldTypeName() {
+ return type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ U.writeString(out, schemaName);
+ U.writeString(out, typeName);
+ U.writeString(out, name);
+ U.writeString(out, type);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ schemaName = U.readString(in);
+ typeName = U.readString(in);
+ name = U.readString(in);
+ type = U.readString(in);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(SqlFieldMetadata.class, this);
+ }
+ }
+
+ /**
+ * Database schema object.
+ */
+ private static class Schema extends ConcurrentHashMap8<String, TableDescriptor> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ private final String spaceName;
+
+ /**
+ * @param spaceName Space name.
+ */
+ private Schema(@Nullable String spaceName) {
+ this.spaceName = spaceName;
+ }
+ }
+
+ /**
+ * Row descriptor.
+ */
+ private class RowDescriptor implements GridH2RowDescriptor {
+ /** */
+ private final GridQueryTypeDescriptor type;
+
+ /** */
+ private final String[] fields;
+
+ /** */
+ private final int[] fieldTypes;
+
+ /** */
+ private final int keyType;
+
+ /** */
+ private final int valType;
+
+ /** */
+ private final Schema schema;
+
+ /** */
+ private final int keyCols;
+
+ /** */
+ private final GridUnsafeGuard guard = offheap == null ? null : new GridUnsafeGuard();
+
+ /**
+ * @param type Type descriptor.
+ * @param schema Schema.
+ * @param keyAsObj Store key as java object.
+ */
+ RowDescriptor(GridQueryTypeDescriptor type, Schema schema, boolean keyAsObj) {
+ assert type != null;
+ assert schema != null;
+
+ this.type = type;
+ this.schema = schema;
+
+ keyCols = type.keyFields().size();
+
+ Map<String, Class<?>> allFields = new LinkedHashMap<>();
+
+ allFields.putAll(type.keyFields());
+ allFields.putAll(type.valueFields());
+
+ fields = allFields.keySet().toArray(new String[allFields.size()]);
+
+ fieldTypes = new int[fields.length];
+
+ Class[] classes = allFields.values().toArray(new Class[fields.length]);
+
+ for (int i = 0; i < fieldTypes.length; i++)
+ fieldTypes[i] = DataType.getTypeFromClass(classes[i]);
+
+ keyType = keyAsObj ? Value.JAVA_OBJECT : DataType.getTypeFromClass(type.keyClass());
+ valType = DataType.getTypeFromClass(type.valueClass());
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridUnsafeGuard guard() {
+ return guard;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void cache(GridH2KeyValueRowOffheap row) {
+ long ptr = row.pointer();
+
+ assert ptr > 0 : ptr;
+
+ rowCache.put(ptr, row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void uncache(long ptr) {
+ rowCache.remove(ptr);
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridUnsafeMemory memory() {
+ return offheap;
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2Indexing owner() {
+ return GridH2Indexing.this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2AbstractKeyValueRow createRow(Object key, @Nullable Object val, long expirationTime)
+ throws GridException {
+ try {
+ return offheap == null ?
+ new GridH2KeyValueRowOnheap(this, key, keyType, val, valType, expirationTime) :
+ new GridH2KeyValueRowOffheap(this, key, keyType, val, valType, expirationTime);
+ }
+ catch (ClassCastException e) {
+ throw new GridException("Failed to convert key to SQL type. " +
+ "Please make sure that you always store each value type with the same key type or disable " +
+ "'defaultIndexFixedTyping' property on GridH2IndexingSpi.", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public Object readFromSwap(Object key) throws GridException {
+ GridCache<Object, ?> cache = ctx.cache().cache(schema.spaceName);
+
+ GridCacheContext cctx = ((GridCacheProxyImpl)cache).context();
+
+ if (cctx.isNear())
+ cctx = cctx.near().dht().context();
+
+ GridCacheSwapEntry e = cctx.swap().read(key);
+
+ return e != null ? e.value() : null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int valueType() {
+ return valType;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int fieldsCount() {
+ return fields.length;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int fieldType(int col) {
+ return fieldTypes[col];
+ }
+
+ /** {@inheritDoc} */
+ @Override public Object columnValue(Object obj, int col) {
+ try {
+ return type.value(obj, fields[col]);
+ }
+ catch (GridException e) {
+ throw DbException.convert(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isKeyColumn(int col) {
+ return keyCols > col;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean valueToString() {
+ return type.valueTextIndex();
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2KeyValueRowOffheap createPointer(long ptr) {
+ GridH2KeyValueRowOffheap row = rowCache.get(ptr);
+
+ if (row != null) {
+ assert row.pointer() == ptr : ptr + " " + row.pointer();
+
+ return row;
+ }
+
+ return new GridH2KeyValueRowOffheap(this, ptr);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2ResultSetIterator.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2ResultSetIterator.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2ResultSetIterator.java
new file mode 100644
index 0000000..a231144
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2ResultSetIterator.java
@@ -0,0 +1,122 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2;
+
+import org.gridgain.grid.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.typedef.internal.*;
+
+import java.sql.*;
+import java.util.*;
+
+
+/**
+ * Iterator over result set.
+ */
+abstract class GridH2ResultSetIterator<T> extends GridCloseableIteratorAdapter<T> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ private final ResultSet data;
+
+ /** */
+ protected final Object[] row;
+
+ /** */
+ private boolean hasRow;
+
+ /**
+ * @param data Data array.
+ * @throws GridException If failed.
+ */
+ protected GridH2ResultSetIterator(ResultSet data) throws GridException {
+ this.data = data;
+
+ if (data != null) {
+ try {
+ row = new Object[data.getMetaData().getColumnCount()];
+ }
+ catch (SQLException e) {
+ throw new GridException(e);
+ }
+ }
+ else
+ row = null;
+ }
+
+ /**
+ * @return {@code true} If next row was fetched successfully.
+ */
+ private boolean fetchNext() {
+ if (data == null)
+ return false;
+
+ try {
+ if (!data.next())
+ return false;
+
+ for (int c = 0; c < row.length; c++)
+ row[c] = data.getObject(c + 1);
+
+ return true;
+ }
+ catch (SQLException e) {
+ throw new GridRuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean onHasNext() {
+ return hasRow || (hasRow = fetchNext());
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("IteratorNextCanNotThrowNoSuchElementException")
+ @Override public T onNext() {
+ if (!hasNext())
+ throw new NoSuchElementException();
+
+ hasRow = false;
+
+ return createRow();
+ }
+
+ /**
+ * @return Row.
+ */
+ protected abstract T createRow();
+
+ /** {@inheritDoc} */
+ @Override public void onRemove() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onClose() throws GridException {
+ if (data == null)
+ // Nothing to close.
+ return;
+
+ try {
+ U.closeQuiet(data.getStatement());
+ }
+ catch (SQLException e) {
+ throw new GridException(e);
+ }
+
+ U.closeQuiet(data);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString((Class<GridH2ResultSetIterator>)getClass(), this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java
new file mode 100644
index 0000000..ee96666
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java
@@ -0,0 +1,447 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.ignite.spi.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.kernal.processors.query.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.h2.message.*;
+import org.h2.result.*;
+import org.h2.value.*;
+import org.jetbrains.annotations.*;
+
+import java.lang.ref.*;
+import java.math.*;
+import java.sql.Date;
+import java.sql.*;
+import java.util.*;
+
+/**
+ * Table row implementation based on {@link GridQueryTypeDescriptor}.
+ */
+public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
+ /** */
+ private static final int DEFAULT_COLUMNS_COUNT = 2;
+
+ /** Key column. */
+ public static final int KEY_COL = 0;
+
+ /** Value column. */
+ public static final int VAL_COL = 1;
+
+ /** */
+ protected final GridH2RowDescriptor desc;
+
+ /** */
+ @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
+ protected long expirationTime;
+
+ /**
+ * Constructor.
+ *
+ * @param desc Row descriptor.
+ * @param key Key.
+ * @param keyType Key type.
+ * @param val Value.
+ * @param valType Value type.
+ * @param expirationTime Expiration time.
+ * @throws IgniteSpiException If failed.
+ */
+ protected GridH2AbstractKeyValueRow(GridH2RowDescriptor desc, Object key, int keyType, @Nullable Object val,
+ int valType, long expirationTime) throws IgniteSpiException {
+ super(wrap(key, keyType),
+ val == null ? null : wrap(val, valType)); // We remove by key only, so value can be null here.
+
+ this.desc = desc;
+ this.expirationTime = expirationTime;
+ }
+
+ /**
+ * Protected constructor for {@link GridH2KeyValueRowOffheap}
+ *
+ * @param desc Row descriptor.
+ */
+ protected GridH2AbstractKeyValueRow(GridH2RowDescriptor desc) {
+ super(new Value[DEFAULT_COLUMNS_COUNT]);
+
+ this.desc = desc;
+ }
+
+ /**
+ * Wraps object to respective {@link Value}.
+ *
+ * @param obj Object.
+ * @param type Value type.
+ * @return Value.
+ * @throws IgniteSpiException If failed.
+ */
+ private static Value wrap(Object obj, int type) throws IgniteSpiException {
+ switch (type) {
+ case Value.BOOLEAN:
+ return ValueBoolean.get((Boolean)obj);
+ case Value.BYTE:
+ return ValueByte.get((Byte)obj);
+ case Value.SHORT:
+ return ValueShort.get((Short)obj);
+ case Value.INT:
+ return ValueInt.get((Integer)obj);
+ case Value.FLOAT:
+ return ValueFloat.get((Float)obj);
+ case Value.LONG:
+ return ValueLong.get((Long)obj);
+ case Value.DOUBLE:
+ return ValueDouble.get((Double)obj);
+ case Value.UUID:
+ UUID uuid = (UUID)obj;
+ return ValueUuid.get(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
+ case Value.DATE:
+ return ValueDate.get((Date)obj);
+ case Value.TIME:
+ return ValueTime.get((Time)obj);
+ case Value.TIMESTAMP:
+ if (obj instanceof java.util.Date && !(obj instanceof Timestamp))
+ obj = new Timestamp(((java.util.Date) obj).getTime());
+
+ return GridH2Utils.toValueTimestamp((Timestamp)obj);
+ case Value.DECIMAL:
+ return ValueDecimal.get((BigDecimal)obj);
+ case Value.STRING:
+ return ValueString.get(obj.toString());
+ case Value.BYTES:
+ return ValueBytes.get((byte[])obj);
+ case Value.JAVA_OBJECT:
+ return ValueJavaObject.getNoCopy(obj, null, null);
+ case Value.ARRAY:
+ Object[] arr = (Object[])obj;
+
+ Value[] valArr = new Value[arr.length];
+
+ for (int i = 0; i < arr.length; i++) {
+ Object o = arr[i];
+
+ valArr[i] = o == null ? ValueNull.INSTANCE : wrap(o, DataType.getTypeFromClass(o.getClass()));
+ }
+
+ return ValueArray.get(valArr);
+
+ case Value.GEOMETRY:
+ return ValueGeometry.getFromGeometry(obj);
+ }
+
+ throw new IgniteSpiException("Failed to wrap value[type=" + type + ", value=" + obj + "]");
+ }
+
+ /**
+ * @return Expiration time of respective cache entry.
+ */
+ public long expirationTime() {
+ return expirationTime;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getColumnCount() {
+ return DEFAULT_COLUMNS_COUNT + desc.fieldsCount();
+ }
+
+ /**
+ * Should be called to remove reference on value.
+ *
+ * @throws IgniteSpiException If failed.
+ */
+ public synchronized void onSwap() throws GridException {
+ setValue(VAL_COL, null);
+ }
+
+ /**
+ * Should be called when entry getting unswapped.
+ *
+ * @param val Value.
+ * @throws GridException If failed.
+ */
+ public synchronized void onUnswap(Object val) throws GridException {
+ setValue(VAL_COL, wrap(val, desc.valueType()));
+ }
+
+ /**
+ * Atomically updates weak value.
+ *
+ * @param exp Expected value.
+ * @param upd New value.
+ * @return Expected value if update succeeded, unexpected value otherwise.
+ */
+ protected synchronized Value updateWeakValue(Value exp, Value upd) {
+ Value res = super.getValue(VAL_COL);
+
+ if (res != exp && !(res instanceof WeakValue))
+ return res;
+
+ setValue(VAL_COL, new WeakValue(upd));
+
+ return exp;
+ }
+
+ /**
+ * @return Synchronized value.
+ */
+ protected synchronized Value syncValue() {
+ return super.getValue(VAL_COL);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Value getValue(int col) {
+ if (col < DEFAULT_COLUMNS_COUNT) {
+ Value v = super.getValue(col);
+
+ if (col == VAL_COL) {
+ while ((v = WeakValue.unwrap(v)) == null) {
+ v = getOffheapValue(VAL_COL);
+
+ if (v != null) {
+ setValue(VAL_COL, v);
+
+ if (super.getValue(KEY_COL) == null)
+ cache();
+
+ return v;
+ }
+
+ try {
+ Object valObj = desc.readFromSwap(getValue(KEY_COL).getObject());
+
+ if (valObj != null) {
+ Value upd = wrap(valObj, desc.valueType());
+
+ Value res = updateWeakValue(v, upd);
+
+ if (res == v) {
+ if (super.getValue(KEY_COL) == null)
+ cache();
+
+ return upd;
+ }
+
+ v = res;
+ }
+ else {
+ // If nothing found in swap then we should be already unswapped.
+ v = syncValue();
+ }
+ }
+ catch (GridException e) {
+ throw new GridRuntimeException(e);
+ }
+ }
+ }
+
+ if (v == null) {
+ assert col == KEY_COL : col;
+
+ v = getOffheapValue(KEY_COL);
+
+ assert v != null : v;
+
+ setValue(KEY_COL, v);
+
+ if (super.getValue(VAL_COL) == null)
+ cache();
+ }
+
+ assert !(v instanceof WeakValue) : v;
+
+ return v;
+ }
+
+ col -= DEFAULT_COLUMNS_COUNT;
+
+ assert col >= 0;
+
+ Value v = getValue(desc.isKeyColumn(col) ? KEY_COL : VAL_COL);
+
+ if (v == null)
+ return null;
+
+ Object obj = v.getObject();
+
+ Object res = desc.columnValue(obj, col);
+
+ if (res == null)
+ return ValueNull.INSTANCE;
+
+ try {
+ return wrap(res, desc.fieldType(col));
+ }
+ catch (IgniteSpiException e) {
+ throw DbException.convert(e);
+ }
+ }
+
+ /**
+ * Caches this row for reuse.
+ */
+ protected abstract void cache();
+
+ /**
+ * @param col Column.
+ * @return Value read from offheap memory or null if it is impossible.
+ */
+ protected abstract Value getOffheapValue(int col);
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ SB sb = new SB("Row@");
+
+ sb.a(Integer.toHexString(System.identityHashCode(this)));
+
+ Value v = super.getValue(KEY_COL);
+ sb.a("[ key: ").a(v == null ? "nil" : v.getString());
+
+ v = WeakValue.unwrap(super.getValue(VAL_COL));
+ sb.a(", val: ").a(v == null ? "nil" : v.getString());
+
+ sb.a(" ][ ");
+
+ if (v != null) {
+ for (int i = 2, cnt = getColumnCount(); i < cnt; i++) {
+ v = getValue(i);
+
+ if (i != 2)
+ sb.a(", ");
+
+ sb.a(v == null ? "nil" : v.getString());
+ }
+ }
+
+ sb.a(" ]");
+
+ return sb.toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setKeyAndVersion(SearchRow old) {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setKey(long key) {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Row getCopy() {
+ assert false;
+
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setDeleted(boolean deleted) {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getKey() {
+ assert false;
+
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setSessionId(int sesId) {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setVersion(int ver) {
+ assert false;
+ }
+
+ /**
+ * Weak reference to value that was swapped but accessed in indexing SPI.
+ */
+ private static class WeakValue extends Value {
+ /**
+ * Unwraps value.
+ *
+ * @param v Value.
+ * @return Unwrapped value.
+ */
+ static Value unwrap(Value v) {
+ return (v instanceof WeakValue) ? ((WeakValue)v).get() : v;
+ }
+
+ /** */
+ private final WeakReference<Value> ref;
+
+ /**
+ * @param v Value.
+ */
+ private WeakValue(Value v) {
+ ref = new WeakReference<>(v);
+ }
+
+ /**
+ * @return Referenced value.
+ */
+ public Value get() {
+ return ref.get();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getSQL() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getType() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getPrecision() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getDisplaySize() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getString() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Object getObject() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void set(PreparedStatement preparedStatement, int i) throws SQLException {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected int compareSecure(Value val, CompareMode compareMode) {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ throw new IllegalStateException();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Cursor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Cursor.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Cursor.java
new file mode 100644
index 0000000..5cc3711
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Cursor.java
@@ -0,0 +1,62 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.h2.index.*;
+import org.h2.message.*;
+import org.h2.result.*;
+
+import java.util.*;
+
+/**
+ * H2 Cursor implementation.
+ */
+public class GridH2Cursor implements Cursor {
+ /** */
+ private Iterator<GridH2Row> iter;
+
+ /** */
+ private Row row;
+
+ /**
+ * Constructor.
+ *
+ * @param iter Rows iterator.
+ */
+ public GridH2Cursor(Iterator<GridH2Row> iter) {
+ this.iter = iter;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Row get() {
+ return row;
+ }
+
+ /** {@inheritDoc} */
+ @Override public SearchRow getSearchRow() {
+ return get();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean next() {
+ row = null;
+
+ if (iter.hasNext())
+ row = iter.next();
+
+ return row != null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean previous() {
+ // Should never be called.
+ throw DbException.getUnsupportedException("previous");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2IndexBase.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2IndexBase.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2IndexBase.java
new file mode 100644
index 0000000..00cb06d
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2IndexBase.java
@@ -0,0 +1,198 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.indexing.*;
+import org.gridgain.grid.util.lang.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.h2.engine.*;
+import org.h2.index.*;
+import org.h2.message.*;
+import org.h2.result.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+/**
+ * Index base.
+ */
+public abstract class GridH2IndexBase extends BaseIndex {
+ /** */
+ protected static final ThreadLocal<GridIndexingQueryFilter> filters = new ThreadLocal<>();
+
+ /** */
+ protected final int keyCol;
+
+ /** */
+ protected final int valCol;
+
+ /**
+ * @param keyCol Key column.
+ * @param valCol Value column.
+ */
+ protected GridH2IndexBase(int keyCol, int valCol) {
+ this.keyCol = keyCol;
+ this.valCol = valCol;
+ }
+
+ /**
+ * Sets key filters for current thread.
+ *
+ * @param fs Filters.
+ */
+ public static void setFiltersForThread(GridIndexingQueryFilter fs) {
+ filters.set(fs);
+ }
+
+ /**
+ * If the index supports rebuilding it has to creates its own copy.
+ *
+ * @return Rebuilt copy.
+ * @throws InterruptedException If interrupted.
+ */
+ public GridH2IndexBase rebuild() throws InterruptedException {
+ return this;
+ }
+
+ /**
+ * Put row if absent.
+ *
+ * @param row Row.
+ * @return Existing row or {@code null}.
+ */
+ public abstract GridH2Row put(GridH2Row row);
+
+ /**
+ * Remove row from index.
+ *
+ * @param row Row.
+ * @return Removed row.
+ */
+ public abstract GridH2Row remove(SearchRow row);
+
+ /**
+ * Takes or sets existing snapshot to be used in current thread.
+ *
+ * @param s Optional existing snapshot to use.
+ * @return Snapshot.
+ */
+ public Object takeSnapshot(@Nullable Object s) {
+ return s;
+ }
+
+ /**
+ * Releases snapshot for current thread.
+ */
+ public void releaseSnapshot() {
+ // No-op.
+ }
+
+ /**
+ * Filters rows from expired ones and using predicate.
+ *
+ * @param iter Iterator over rows.
+ * @return Filtered iterator.
+ */
+ protected Iterator<GridH2Row> filter(Iterator<GridH2Row> iter) {
+ IgniteBiPredicate<Object, Object> p = null;
+
+ GridIndexingQueryFilter f = filters.get();
+
+ if (f != null) {
+ String spaceName = ((GridH2Table)getTable()).spaceName();
+
+ p = f.forSpace(spaceName);
+ }
+
+ return new FilteringIterator(iter, U.currentTimeMillis(), p);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDiskSpaceUsed() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void checkRename() {
+ throw DbException.getUnsupportedException("rename");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void add(Session ses, Row row) {
+ throw DbException.getUnsupportedException("add");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(Session ses, Row row) {
+ throw DbException.getUnsupportedException("remove row");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(Session ses) {
+ throw DbException.getUnsupportedException("remove index");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void truncate(Session ses) {
+ throw DbException.getUnsupportedException("truncate");
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean needRebuild() {
+ return false;
+ }
+
+ /**
+ * Iterator which filters by expiration time and predicate.
+ */
+ protected class FilteringIterator extends GridFilteredIterator<GridH2Row> {
+ /** */
+ private final IgniteBiPredicate<Object, Object> fltr;
+
+ /** */
+ private final long time;
+
+ /**
+ * @param iter Iterator.
+ * @param time Time for expired rows filtering.
+ */
+ protected FilteringIterator(Iterator<GridH2Row> iter, long time,
+ IgniteBiPredicate<Object, Object> fltr) {
+ super(iter);
+
+ this.time = time;
+ this.fltr = fltr;
+ }
+
+ /**
+ * @param row Row.
+ * @return If this row was accepted.
+ */
+ @SuppressWarnings("unchecked")
+ @Override protected boolean accept(GridH2Row row) {
+ if (row instanceof GridH2AbstractKeyValueRow) {
+ if (((GridH2AbstractKeyValueRow) row).expirationTime() <= time)
+ return false;
+ }
+
+ if (fltr == null)
+ return true;
+
+ Object key = row.getValue(keyCol).getObject();
+ Object val = row.getValue(valCol).getObject();
+
+ assert key != null;
+ assert val != null;
+
+ return fltr.apply(key, val);
+ }
+ }
+}
[03/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TreeIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TreeIndex.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TreeIndex.java
deleted file mode 100644
index 9788414..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2TreeIndex.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.ignite.spi.indexing.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.*;
-import org.gridgain.grid.util.snaptree.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-import org.h2.engine.*;
-import org.h2.index.*;
-import org.h2.index.IndexType;
-import org.h2.result.*;
-import org.h2.table.*;
-import org.h2.value.*;
-import org.jetbrains.annotations.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-/**
- * Base class for snapshotable tree indexes.
- */
-@SuppressWarnings("ComparatorNotSerializable")
-public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridSearchRowPointer> {
- /** */
- protected final ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree;
-
- /** */
- private final ThreadLocal<ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>> snapshot =
- new ThreadLocal<>();
-
- /**
- * Constructor with index initialization.
- *
- * @param name Index name.
- * @param tbl Table.
- * @param pk If this index is primary key.
- * @param keyCol Primary key column index.
- * @param valCol Value column index.
- * @param cols Index columns list.
- */
- @SuppressWarnings("unchecked")
- public GridH2TreeIndex(String name, GridH2Table tbl, boolean pk, int keyCol, int valCol, IndexColumn... cols) {
- super(keyCol, valCol);
- if (!pk) {
- // For other indexes we add primary key at the end to avoid conflicts.
- cols = Arrays.copyOf(cols, cols.length + 1);
-
- cols[cols.length - 1] = tbl.indexColumn(keyCol, SortOrder.ASCENDING);
- }
-
- IndexColumn.mapColumns(cols, tbl);
-
- initBaseIndex(tbl, 0, name, cols,
- pk ? IndexType.createUnique(false, false) : IndexType.createNonUnique(false, false, false));
-
- final GridH2RowDescriptor desc = tbl.rowDescriptor();
-
- tree = desc == null || desc.memory() == null ? new SnapTreeMap<GridSearchRowPointer, GridH2Row>(this) {
- @Override protected void afterNodeUpdate_nl(Node<GridSearchRowPointer, GridH2Row> node, Object val) {
- if (val != null)
- node.key = (GridSearchRowPointer)val;
- }
-
- @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
- if (key instanceof ComparableRow)
- return (Comparable<? super SearchRow>)key;
-
- return super.comparable(key);
- }
- } : new GridOffHeapSnapTreeMap<GridSearchRowPointer, GridH2Row>(desc, desc, desc.memory(), desc.guard(), this) {
- @Override protected void afterNodeUpdate_nl(long node, GridH2Row val) {
- final long oldKey = keyPtr(node);
-
- if (val != null) {
- key(node, val);
-
- guard.finalizeLater(new Runnable() {
- @Override public void run() {
- desc.createPointer(oldKey).decrementRefCount();
- }
- });
- }
- }
-
- @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
- if (key instanceof ComparableRow)
- return (Comparable<? super SearchRow>)key;
-
- return super.comparable(key);
- }
- };
- }
-
- /**
- * Closes index and releases resources.
- */
- public void close() {
- if (tree instanceof Closeable)
- U.closeQuiet((Closeable)tree);
- }
-
- /**
- * Takes snapshot to be used in current thread. If argument is null it will be taken from current trees.
- *
- * @param s Map to be used as snapshot if not null.
- * @return Taken snapshot or given argument back.
- */
- @SuppressWarnings("unchecked")
- @Override public Object takeSnapshot(@Nullable Object s) {
- assert snapshot.get() == null;
-
- if (s == null)
- s = tree instanceof SnapTreeMap ? ((SnapTreeMap)tree).clone() :
- ((GridOffHeapSnapTreeMap)tree).clone();
-
- snapshot.set((ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>)s);
-
- return s;
- }
-
- /**
- * Releases snapshot for current thread.
- */
- @Override public void releaseSnapshot() {
- ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> s = snapshot.get();
-
- snapshot.remove();
-
- if (s instanceof Closeable)
- U.closeQuiet((Closeable)s);
- }
-
- /**
- * @return Snapshot for current thread if there is one.
- */
- private ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> treeForRead() {
- ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> res = snapshot.get();
-
- if (res == null)
- res = tree;
-
- return res;
- }
-
- /** {@inheritDoc} */
- @Override public void close(Session ses) {
- assert snapshot.get() == null;
-
- if (tree instanceof Closeable)
- U.closeQuiet((Closeable)tree);
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCount(@Nullable Session ses) {
- IndexingQueryFilter f = filters.get();
-
- try { // Fast path if we don't need to perform any filtering.
- if (f == null || f.forSpace(((GridH2Table)getTable()).spaceName()) == null)
- return treeForRead().size();
- }
- catch (GridException e) {
- throw new GridRuntimeException(e);
- }
-
- Iterator<GridH2Row> iter = doFind(null, false, null);
-
- long size = 0;
-
- while (iter.hasNext()) {
- iter.next();
-
- size++;
- }
-
- return size;
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCountApproximation() {
- return tree.size();
- }
-
- /** {@inheritDoc} */
- @Override public int compare(GridSearchRowPointer r1, GridSearchRowPointer r2) {
- // Second row here must be data row if first is a search row.
- return -compareRows(r2, r1);
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- SB sb = new SB((indexType.isUnique() ? "Unique index '" : "Index '") + getName() + "' [");
-
- boolean first = true;
-
- for (IndexColumn col : getIndexColumns()) {
- if (first)
- first = false;
- else
- sb.a(", ");
-
- sb.a(col.getSQL());
- }
-
- sb.a(" ]");
-
- return sb.toString();
- }
-
- /** {@inheritDoc} */
- @Override public double getCost(Session ses, int[] masks, TableFilter filter, SortOrder sortOrder) {
- return getCostRangeIndex(masks, getRowCountApproximation(), filter, sortOrder);
- }
-
- /** {@inheritDoc} */
- @Override public boolean canFindNext() {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public Cursor find(Session ses, @Nullable SearchRow first, @Nullable SearchRow last) {
- return new GridH2Cursor(doFind(first, true, last));
- }
-
- /** {@inheritDoc} */
- @Override public Cursor findNext(Session ses, SearchRow higherThan, SearchRow last) {
- return new GridH2Cursor(doFind(higherThan, false, last));
- }
-
- /**
- * Finds row with key equal one in given search row.
- * WARNING!! Method call must be protected by {@link GridUnsafeGuard#begin()}
- * {@link GridUnsafeGuard#end()} block.
- *
- * @param row Search row.
- * @return Row.
- */
- public GridH2AbstractKeyValueRow findOne(GridSearchRowPointer row) {
- return (GridH2AbstractKeyValueRow)tree.get(row);
- }
-
- /**
- * Returns sub-tree bounded by given values.
- *
- * @param first Lower bound.
- * @param includeFirst Whether lower bound should be inclusive.
- * @param last Upper bound always inclusive.
- * @return Iterator over rows in given range.
- */
- @SuppressWarnings("unchecked")
- private Iterator<GridH2Row> doFind(@Nullable SearchRow first, boolean includeFirst,
- @Nullable SearchRow last) {
- ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> t = treeForRead();
-
- includeFirst &= first != null;
-
- NavigableMap<GridSearchRowPointer, GridH2Row> range = subTree(t, comparable(first, includeFirst ? -1 : 1),
- comparable(last, 1));
-
- if (range == null)
- return new GridEmptyIterator<>();
-
- return filter(range.values().iterator());
- }
-
- /**
- * @param row Row.
- * @param bias Bias.
- * @return Comparable row.
- */
- private GridSearchRowPointer comparable(SearchRow row, int bias) {
- if (row == null)
- return null;
-
- if (bias == 0 && row instanceof GridH2Row)
- return (GridSearchRowPointer)row;
-
- return new ComparableRow(row, bias);
- }
-
- /**
- * Takes sup-map from given one.
- *
- * @param map Map.
- * @param first Lower bound.
- * @param last Upper bound.
- * @return Sub-map.
- */
- @SuppressWarnings({"IfMayBeConditional", "TypeMayBeWeakened"})
- private NavigableMap<GridSearchRowPointer, GridH2Row> subTree(NavigableMap<GridSearchRowPointer, GridH2Row> map,
- @Nullable GridSearchRowPointer first, @Nullable GridSearchRowPointer last) {
- // We take exclusive bounds because it is possible that one search row will be equal to multiple key rows
- // in tree and we must return them all.
- if (first == null) {
- if (last == null)
- return map;
- else
- return map.headMap(last, false);
- }
- else {
- if (last == null)
- return map.tailMap(first, false);
- else {
- if (compare(first, last) > 0)
- return null;
-
- return map.subMap(first, false, last, false);
- }
- }
- }
-
- /**
- * Gets iterator over all rows in this index.
- *
- * @return Rows iterator.
- */
- Iterator<GridH2Row> rows() {
- return doFind(null, false, null);
- }
-
- /** {@inheritDoc} */
- @Override public boolean canGetFirstOrLast() {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public Cursor findFirstOrLast(Session ses, boolean first) {
- ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree = treeForRead();
-
- GridSearchRowPointer res = null;
-
- Iterator<GridH2Row> iter = filter(first ? tree.values().iterator() :
- tree.descendingMap().values().iterator());
-
- if (iter.hasNext()) {
- GridSearchRowPointer r = iter.next();
-
- if ((first && compare(r, res) < 0) || (!first && compare(r, res) > 0))
- res = r;
- }
-
- return new SingleRowCursor((Row)res);
- }
-
- /** {@inheritDoc} */
- @Override public GridH2Row put(GridH2Row row) {
- return tree.put(row, row);
- }
-
- /** {@inheritDoc} */
- @Override public GridH2Row remove(SearchRow row) {
- return tree.remove(comparable(row, 0));
- }
-
- /**
- * Comparable row with bias. Will be used for queries to have correct bounds (in case of multicolumn index
- * and query on few first columns we will multiple equal entries in tree).
- */
- private class ComparableRow implements GridSearchRowPointer, Comparable<SearchRow> {
- /** */
- private final SearchRow row;
-
- /** */
- private final int bias;
-
- /**
- * @param row Row.
- * @param bias Bias.
- */
- private ComparableRow(SearchRow row, int bias) {
- this.row = row;
- this.bias = bias;
- }
-
- /** {@inheritDoc} */
- @Override public int compareTo(SearchRow o) {
- int res = compareRows(o, row);
-
- if (res == 0)
- return bias;
-
- return -res;
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(Object obj) {
- throw new IllegalStateException("Should never be called.");
- }
-
- /** {@inheritDoc} */
- @Override public int getColumnCount() {
- return row.getColumnCount();
- }
-
- /** {@inheritDoc} */
- @Override public Value getValue(int idx) {
- return row.getValue(idx);
- }
-
- /** {@inheritDoc} */
- @Override public void setValue(int idx, Value v) {
- row.setValue(idx, v);
- }
-
- /** {@inheritDoc} */
- @Override public void setKeyAndVersion(SearchRow old) {
- row.setKeyAndVersion(old);
- }
-
- /** {@inheritDoc} */
- @Override public int getVersion() {
- return row.getVersion();
- }
-
- /** {@inheritDoc} */
- @Override public void setKey(long key) {
- row.setKey(key);
- }
-
- /** {@inheritDoc} */
- @Override public long getKey() {
- return row.getKey();
- }
-
- /** {@inheritDoc} */
- @Override public int getMemory() {
- return row.getMemory();
- }
-
- /** {@inheritDoc} */
- @Override public long pointer() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public void incrementRefCount() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public void decrementRefCount() {
- throw new IllegalStateException();
- }
- }
-
- /** {@inheritDoc} */
- @Override public GridH2TreeIndex rebuild() throws InterruptedException {
- IndexColumn[] cols = getIndexColumns();
-
- if (!getIndexType().isUnique())
- cols = Arrays.copyOf(cols, cols.length - 1);
-
- GridH2TreeIndex idx = new GridH2TreeIndex(getName(), (GridH2Table)getTable(), getIndexType().isUnique(),
- keyCol, valCol, cols);
-
- Thread thread = Thread.currentThread();
-
- long i = 0;
-
- for (GridH2Row row : tree.values()) {
- // Check for interruptions every 1000 iterations.
- if (++i % 1000 == 0 && thread.isInterrupted())
- throw new InterruptedException();
-
- idx.tree.put(row, row);
- }
-
- return idx;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Utils.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Utils.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Utils.java
deleted file mode 100644
index cf5668f..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Utils.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.h2.value.*;
-
-import java.sql.*;
-import java.util.*;
-
-/**
- *
- */
-@SuppressWarnings({"JavaAbbreviationUsage", "GridBracket"})
-public class GridH2Utils {
- /** Copy/pasted from org.h2.util.DateTimeUtils */
- private static final int SHIFT_YEAR = 9;
-
- /** Copy/pasted from org.h2.util.DateTimeUtils */
- private static final int SHIFT_MONTH = 5;
-
- /** Static calendar. */
- private static final Calendar staticCalendar = Calendar.getInstance();
-
- /** */
- private static final ThreadLocal<Calendar> localCalendar = new ThreadLocal<>();
-
- /**
- * @return The instance of calendar for local thread.
- */
- public static Calendar getLocalCalendar() {
- Calendar res = localCalendar.get();
-
- if (res == null) {
- res = (Calendar)staticCalendar.clone();
-
- localCalendar.set(res);
- }
-
- return res;
- }
-
- /**
- * Get or create a timestamp value for the given timestamp.
- *
- * Copy/pasted from org.h2.value.ValueTimestamp#get(java.sql.Timestamp)
- *
- * @param timestamp The timestamp.
- * @return The value.
- */
- public static ValueTimestamp toValueTimestamp(Timestamp timestamp) {
- long ms = timestamp.getTime();
- long nanos = timestamp.getNanos() % 1000000;
-
- Calendar calendar = getLocalCalendar();
-
- calendar.clear();
- calendar.setTimeInMillis(ms);
-
- long dateValue = dateValueFromCalendar(calendar);
-
- nanos += nanosFromCalendar(calendar);
-
- return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
- }
-
- /**
- * Calculate the nanoseconds since midnight from a given calendar.
- *
- * Copy/pasted from org.h2.util.DateTimeUtils#nanosFromCalendar(java.util.Calendar).
- *
- * @param cal The calendar.
- * @return Nanoseconds.
- */
- private static long nanosFromCalendar(Calendar cal) {
- int h = cal.get(Calendar.HOUR_OF_DAY);
- int m = cal.get(Calendar.MINUTE);
- int s = cal.get(Calendar.SECOND);
- int millis = cal.get(Calendar.MILLISECOND);
-
- return ((((((h * 60L) + m) * 60) + s) * 1000) + millis) * 1000000;
- }
-
- /**
- * Calculate the date value from a given calendar.
- *
- * Copy/pasted from org.h2.util.DateTimeUtils#dateValueFromCalendar(java.util.Calendar)
- *
- * @param cal The calendar.
- * @return The date value.
- */
- private static long dateValueFromCalendar(Calendar cal) {
- int year, month, day;
-
- year = getYear(cal);
- month = cal.get(Calendar.MONTH) + 1;
- day = cal.get(Calendar.DAY_OF_MONTH);
-
- return ((long) year << SHIFT_YEAR) | (month << SHIFT_MONTH) | day;
- }
-
- /**
- * Get the year (positive or negative) from a calendar.
- *
- * Copy/pasted from org.h2.util.DateTimeUtils#getYear(java.util.Calendar)
- *
- * @param calendar The calendar.
- * @return The year.
- */
- private static int getYear(Calendar calendar) {
- int year = calendar.get(Calendar.YEAR);
-
- if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
- year = 1 - year;
- }
-
- return year;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneDirectory.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneDirectory.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneDirectory.java
deleted file mode 100644
index e934902..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneDirectory.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.lucene.store.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-/**
- * A memory-resident {@link Directory} implementation.
- */
-public class GridLuceneDirectory extends Directory {
- /** */
- protected final Map<String, GridLuceneFile> fileMap = new ConcurrentHashMap<>();
-
- /** */
- protected final AtomicLong sizeInBytes = new AtomicLong();
-
- /** */
- private final GridUnsafeMemory mem;
-
- /**
- * Constructs an empty {@link Directory}.
- *
- * @param mem Memory.
- */
- public GridLuceneDirectory(GridUnsafeMemory mem) {
- this.mem = mem;
-
- try {
- setLockFactory(new GridLuceneLockFactory());
- }
- catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override public final String[] listAll() {
- ensureOpen();
- // NOTE: fileMap.keySet().toArray(new String[0]) is broken in non Sun JDKs,
- // and the code below is resilient to map changes during the array population.
- Set<String> fileNames = fileMap.keySet();
-
- List<String> names = new ArrayList<>(fileNames.size());
-
- for (String name : fileNames)
- names.add(name);
-
- return names.toArray(new String[names.size()]);
- }
-
- /** {@inheritDoc} */
- @Override public final boolean fileExists(String name) {
- ensureOpen();
-
- return fileMap.containsKey(name);
- }
-
- /** {@inheritDoc} */
- @Override public final long fileModified(String name) {
- ensureOpen();
-
- throw new IllegalStateException(name);
- }
-
- /**
- * Set the modified time of an existing file to now.
- *
- * @throws IOException if the file does not exist
- */
- @Override public void touchFile(String name) throws IOException {
- ensureOpen();
-
- throw new IllegalStateException(name);
- }
-
- /** {@inheritDoc} */
- @Override public final long fileLength(String name) throws IOException {
- ensureOpen();
-
- GridLuceneFile file = fileMap.get(name);
-
- if (file == null)
- throw new FileNotFoundException(name);
-
- return file.getLength();
- }
-
- /** {@inheritDoc} */
- @Override public void deleteFile(String name) throws IOException {
- ensureOpen();
-
- doDeleteFile(name);
- }
-
- /**
- * Deletes file.
- *
- * @param name File name.
- * @throws IOException If failed.
- */
- private void doDeleteFile(String name) throws IOException {
- GridLuceneFile file = fileMap.remove(name);
-
- if (file != null) {
- file.delete();
-
- sizeInBytes.addAndGet(-file.getSizeInBytes());
- }
- else
- throw new FileNotFoundException(name);
- }
-
- /** {@inheritDoc} */
- @Override public IndexOutput createOutput(String name) throws IOException {
- ensureOpen();
-
- GridLuceneFile file = newRAMFile();
-
- GridLuceneFile existing = fileMap.remove(name);
-
- if (existing != null) {
- sizeInBytes.addAndGet(-existing.getSizeInBytes());
-
- existing.delete();
- }
-
- fileMap.put(name, file);
-
- return new GridLuceneOutputStream(file);
- }
-
- /**
- * Returns a new {@link GridLuceneFile} for storing data. This method can be
- * overridden to return different {@link GridLuceneFile} impls, that e.g. override.
- *
- * @return New ram file.
- */
- protected GridLuceneFile newRAMFile() {
- return new GridLuceneFile(this);
- }
-
- /** {@inheritDoc} */
- @Override public IndexInput openInput(String name) throws IOException {
- ensureOpen();
-
- GridLuceneFile file = fileMap.get(name);
-
- if (file == null)
- throw new FileNotFoundException(name);
-
- return new GridLuceneInputStream(name, file);
- }
-
- /** {@inheritDoc} */
- @Override public void close() {
- isOpen = false;
-
- for (String fileName : fileMap.keySet()) {
- try {
- doDeleteFile(fileName);
- }
- catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
-
- assert fileMap.isEmpty();
- }
-
- /**
- * @return Memory.
- */
- GridUnsafeMemory memory() {
- return mem;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneFile.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneFile.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneFile.java
deleted file mode 100644
index c8241bb..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneFile.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-import static org.gridgain.grid.spi.indexing.h2.opt.GridLuceneOutputStream.*;
-
-/**
- * Lucene file.
- */
-public class GridLuceneFile implements Serializable {
- /** */
- private static final long serialVersionUID = 0L;
-
- /** */
- public static final AtomicInteger filesCnt = new AtomicInteger();
-
- /** */
- private LongArray buffers = new LongArray();
-
- /** */
- private long length;
-
- /** */
- private final GridLuceneDirectory dir;
-
- /** */
- private volatile long sizeInBytes;
-
- /**
- * File used as buffer, in no RAMDirectory
- *
- * @param dir Directory.
- */
- GridLuceneFile(GridLuceneDirectory dir) {
- this.dir = dir;
-
- filesCnt.incrementAndGet();
- }
-
- /**
- * For non-stream access from thread that might be concurrent with writing
- *
- * @return Length.
- */
- public synchronized long getLength() {
- return length;
- }
-
- /**
- * Sets length.
- *
- * @param length Length.
- */
- protected synchronized void setLength(long length) {
- this.length = length;
- }
-
- /**
- * @return New buffer address.
- */
- final long addBuffer() {
- long buf = newBuffer();
-
- synchronized (this) {
- buffers.add(buf);
-
- sizeInBytes += BUFFER_SIZE;
- }
-
- if (dir != null)
- dir.sizeInBytes.getAndAdd(BUFFER_SIZE);
-
- return buf;
- }
-
- /**
- * Gets address of buffer.
- *
- * @param idx Index.
- * @return Pointer.
- */
- protected final synchronized long getBuffer(int idx) {
- return buffers.get(idx);
- }
-
- /**
- * @return Number of buffers.
- */
- protected final synchronized int numBuffers() {
- return buffers.size();
- }
-
- /**
- * Expert: allocate a new buffer.
- * Subclasses can allocate differently.
- *
- * @return allocated buffer.
- */
- protected long newBuffer() {
- return dir.memory().allocate(BUFFER_SIZE);
- }
-
- /**
- * Deletes file and deallocates memory..
- */
- public synchronized void delete() {
- if (buffers == null)
- return;
-
- for (int i = 0; i < buffers.idx; i++)
- dir.memory().release(buffers.arr[i], BUFFER_SIZE);
-
- buffers = null;
-
- filesCnt.decrementAndGet();
- }
-
- /**
- * @return Size in bytes.
- */
- public long getSizeInBytes() {
- return sizeInBytes;
- }
-
- /**
- * @return Directory.
- */
- public GridLuceneDirectory getDirectory() {
- return dir;
- }
-
- /**
- * Simple expandable long[] wrapper.
- */
- private static class LongArray {
- /** */
- private long[] arr = new long[128];
-
- /** */
- private int idx;
-
- /**
- * @return Size.
- */
- int size() {
- return idx;
- }
-
- /**
- * Gets value by index.
- *
- * @param idx Index.
- * @return Value.
- */
- long get(int idx) {
- assert idx < this.idx;
-
- return arr[idx];
- }
-
- /**
- * Adds value.
- *
- * @param val Value.
- */
- void add(long val) {
- int len = arr.length;
-
- if (idx == len)
- arr = Arrays.copyOf(arr, Math.min(len * 2, len + 1024));
-
- arr[idx++] = val;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndex.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndex.java
deleted file mode 100644
index fe55c81..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneIndex.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.commons.codec.binary.*;
-import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.indexing.*;
-import org.apache.lucene.analysis.standard.*;
-import org.apache.lucene.document.*;
-import org.apache.lucene.index.*;
-import org.apache.lucene.queryParser.*;
-import org.apache.lucene.search.*;
-import org.apache.lucene.util.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.*;
-import org.gridgain.grid.util.lang.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.jetbrains.annotations.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-import static org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi.*;
-
-/**
- * Lucene fulltext index.
- */
-public class GridLuceneIndex implements Closeable {
- /** Field name for string representation of value. */
- public static final String VAL_STR_FIELD_NAME = "_gg_val_str__";
-
- /** Field name for value version. */
- public static final String VER_FIELD_NAME = "_gg_ver__";
-
- /** Field name for value expiration time. */
- public static final String EXPIRATION_TIME_FIELD_NAME = "_gg_expires__";
-
- /** */
- private final IndexingMarshaller marshaller;
-
- /** */
- private final String spaceName;
-
- /** */
- private final IndexingTypeDescriptor type;
-
- /** */
- private final IndexWriter writer;
-
- /** */
- private final String[] idxdFields;
-
- /** */
- private final boolean storeVal;
-
- /** */
- private final BitSet keyFields = new BitSet();
-
- /** */
- private final AtomicLong updateCntr = new GridAtomicLong();
-
- /** */
- private final GridLuceneDirectory dir;
-
- /**
- * Constructor.
- *
- * @param marshaller Indexing marshaller.
- * @param mem Unsafe memory.
- * @param spaceName Space name.
- * @param type Type descriptor.
- * @param storeVal Store value in index.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public GridLuceneIndex(IndexingMarshaller marshaller, @Nullable GridUnsafeMemory mem,
- @Nullable String spaceName, IndexingTypeDescriptor type, boolean storeVal) throws IgniteSpiException {
- this.marshaller = marshaller;
- this.spaceName = spaceName;
- this.type = type;
- this.storeVal = storeVal;
-
- dir = new GridLuceneDirectory(mem == null ? new GridUnsafeMemory(0) : mem);
-
- try {
- writer = new IndexWriter(dir, new IndexWriterConfig(Version.LUCENE_30, new StandardAnalyzer(
- Version.LUCENE_30)));
- }
- catch (IOException e) {
- throw new IgniteSpiException(e);
- }
-
- IndexDescriptor idx = null;
-
- for (IndexDescriptor descriptor : type.indexes().values()) {
- if (descriptor.type() == IndexType.FULLTEXT) {
- idx = descriptor;
-
- break;
- }
- }
-
- if (idx != null) {
- Collection<String> fields = idx.fields();
-
- idxdFields = new String[fields.size() + 1];
-
- fields.toArray(idxdFields);
-
- for (int i = 0, len = fields.size() ; i < len; i++)
- keyFields.set(i, type.keyFields().containsKey(idxdFields[i]));
- }
- else {
- assert type.valueTextIndex() || type.valueClass() == String.class;
-
- idxdFields = new String[1];
- }
-
- idxdFields[idxdFields.length - 1] = VAL_STR_FIELD_NAME;
- }
-
- /**
- * Stores given data in this fulltext index.
- *
- * @param key Key.
- * @param val Value.
- * @param ver Version.
- * @param expires Expiration time.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public void store(IndexingEntity<?> key, IndexingEntity<?> val, byte[] ver, long expires)
- throws IgniteSpiException {
- Document doc = new Document();
-
- Object k = key.value();
- Object v = val.value();
-
- boolean stringsFound = false;
-
- if (type.valueTextIndex() || type.valueClass() == String.class) {
- doc.add(new Field(VAL_STR_FIELD_NAME, v.toString(), Field.Store.YES, Field.Index.ANALYZED));
-
- stringsFound = true;
- }
-
- for (int i = 0, last = idxdFields.length - 1; i < last; i++) {
- Object fieldVal = type.value(keyFields.get(i) ? k : v, idxdFields[i]);
-
- if (fieldVal != null) {
- doc.add(new Field(idxdFields[i], fieldVal.toString(), Field.Store.YES, Field.Index.ANALYZED));
-
- stringsFound = true;
- }
- }
-
- String keyStr = Base64.encodeBase64String(marshaller.marshal(key));
-
- try {
- // Delete first to avoid duplicates.
- writer.deleteDocuments(new Term(KEY_FIELD_NAME, keyStr));
-
- if (!stringsFound)
- return; // We did not find any strings to be indexed, will not store data at all.
-
- doc.add(new Field(KEY_FIELD_NAME, keyStr, Field.Store.YES, Field.Index.NOT_ANALYZED));
-
- if (storeVal && type.valueClass() != String.class)
- doc.add(new Field(VAL_FIELD_NAME, marshaller.marshal(val)));
-
- doc.add(new Field(VER_FIELD_NAME, ver));
-
- doc.add(new Field(EXPIRATION_TIME_FIELD_NAME, DateTools.timeToString(expires,
- DateTools.Resolution.MILLISECOND), Field.Store.YES, Field.Index.NOT_ANALYZED));
-
- writer.addDocument(doc);
- }
- catch (IOException e) {
- throw new IgniteSpiException(e);
- }
- finally {
- updateCntr.incrementAndGet();
- }
- }
-
- /**
- * Removes entry for given key from this index.
- *
- * @param key Key.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public void remove(IndexingEntity<?> key) throws IgniteSpiException {
- try {
- writer.deleteDocuments(new Term(KEY_FIELD_NAME, Base64.encodeBase64String(marshaller.marshal(key))));
- }
- catch (IOException e) {
- throw new IgniteSpiException(e);
- }
- finally {
- updateCntr.incrementAndGet();
- }
- }
-
- /**
- * Runs lucene fulltext query over this index.
- *
- * @param qry Query.
- * @param filters Filters over result.
- * @return Query result.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K, V> GridCloseableIterator<IndexingKeyValueRow<K, V>> query(String qry,
- IndexingQueryFilter filters) throws IgniteSpiException {
- IndexReader reader;
-
- try {
- long updates = updateCntr.get();
-
- if (updates != 0) {
- writer.commit();
-
- updateCntr.addAndGet(-updates);
- }
-
- reader = IndexReader.open(writer, true);
- }
- catch (IOException e) {
- throw new IgniteSpiException(e);
- }
-
- IndexSearcher searcher = new IndexSearcher(reader);
-
- MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_30, idxdFields,
- writer.getAnalyzer());
-
- // Filter expired items.
- Filter f = new TermRangeFilter(EXPIRATION_TIME_FIELD_NAME, DateTools.timeToString(U.currentTimeMillis(),
- DateTools.Resolution.MILLISECOND), null, false, false);
-
- TopDocs docs;
-
- try {
- docs = searcher.search(parser.parse(qry), f, Integer.MAX_VALUE);
- }
- catch (Exception e) {
- throw new IgniteSpiException(e);
- }
-
- IgniteBiPredicate<K, V> fltr = null;
-
- if (filters != null) {
- try {
- fltr = filters.forSpace(spaceName);
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
- }
-
- return new It<>(reader, searcher, docs.scoreDocs, fltr);
- }
-
- /** {@inheritDoc} */
- @Override public void close() {
- U.closeQuiet(writer);
- U.closeQuiet(dir);
- }
-
- /**
- * Key-value iterator over fulltext search result.
- */
- private class It<K, V> extends GridCloseableIteratorAdapter<IndexingKeyValueRow<K, V>> {
- /** */
- private static final long serialVersionUID = 0L;
-
- /** */
- private final IndexReader reader;
-
- /** */
- private final IndexSearcher searcher;
-
- /** */
- private final ScoreDoc[] docs;
-
- /** */
- private final IgniteBiPredicate<K, V> filters;
-
- /** */
- private int idx;
-
- /** */
- private IndexingKeyValueRow<K, V> curr;
-
- /**
- * Constructor.
- *
- * @param reader Reader.
- * @param searcher Searcher.
- * @param docs Docs.
- * @param filters Filters over result.
- * @throws org.apache.ignite.spi.IgniteSpiException if failed.
- */
- private It(IndexReader reader, IndexSearcher searcher, ScoreDoc[] docs, IgniteBiPredicate<K, V> filters)
- throws IgniteSpiException {
- this.reader = reader;
- this.searcher = searcher;
- this.docs = docs;
- this.filters = filters;
-
- findNext();
- }
-
- /**
- * Filters key using predicates.
- *
- * @param key Key.
- * @param val Value.
- * @return {@code True} if key passes filter.
- */
- private boolean filter(K key, V val) {
- return filters == null || filters.apply(key, val) ;
- }
-
- /**
- * Finds next element.
- *
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private void findNext() throws IgniteSpiException {
- curr = null;
-
- while (idx < docs.length) {
- Document doc;
-
- try {
- doc = searcher.doc(docs[idx++].doc);
- }
- catch (IOException e) {
- throw new IgniteSpiException(e);
- }
-
- String keyStr = doc.get(KEY_FIELD_NAME);
-
- IndexingEntity<K> k = marshaller.unmarshal(Base64.decodeBase64(keyStr));
-
- byte[] valBytes = doc.getBinaryValue(VAL_FIELD_NAME);
-
- IndexingEntity<V> v = valBytes != null ? marshaller.<V>unmarshal(valBytes) :
- type.valueClass() == String.class ?
- new IndexingEntityAdapter<>((V)doc.get(VAL_STR_FIELD_NAME), null): null;
-
- if (!filter(k.value(), v == null ? null : v.value()))
- continue;
-
- byte[] ver = doc.getBinaryValue(VER_FIELD_NAME);
-
- curr = new IndexingKeyValueRowAdapter<>(k, v, ver);
-
- break;
- }
- }
-
- /** {@inheritDoc} */
- @Override protected IndexingKeyValueRow<K, V> onNext() throws GridException {
- IndexingKeyValueRow<K, V> res = curr;
-
- findNext();
-
- return res;
- }
-
- /** {@inheritDoc} */
- @Override protected boolean onHasNext() throws GridException {
- return curr != null;
- }
-
- /** {@inheritDoc} */
- @Override protected void onClose() throws GridException {
- U.closeQuiet(searcher);
- U.closeQuiet(reader);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneInputStream.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneInputStream.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneInputStream.java
deleted file mode 100644
index 9a509a7..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneInputStream.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.lucene.store.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-
-import java.io.*;
-
-import static org.gridgain.grid.spi.indexing.h2.opt.GridLuceneOutputStream.*;
-
-/**
- * A memory-resident {@link IndexInput} implementation.
- */
-public class GridLuceneInputStream extends IndexInput {
- /** */
- private GridLuceneFile file;
-
- /** */
- private long length;
-
- /** */
- private long currBuf;
-
- /** */
- private int currBufIdx;
-
- /** */
- private int bufPosition;
-
- /** */
- private long bufStart;
-
- /** */
- private int bufLength;
-
- /** */
- private final GridUnsafeMemory mem;
-
- /**
- * Constructor.
- *
- * @param name Name.
- * @param f File.
- * @throws IOException If failed.
- */
- public GridLuceneInputStream(String name, GridLuceneFile f) throws IOException {
- super("RAMInputStream(name=" + name + ")");
-
- file = f;
-
- length = file.getLength();
-
- if (length / BUFFER_SIZE >= Integer.MAX_VALUE)
- throw new IOException("RAMInputStream too large length=" + length + ": " + name);
-
- mem = file.getDirectory().memory();
-
- // make sure that we switch to the
- // first needed buffer lazily
- currBufIdx = -1;
- currBuf = 0;
- }
-
- /** {@inheritDoc} */
- @Override public void close() {
- // nothing to do here
- }
-
- /** {@inheritDoc} */
- @Override public long length() {
- return length;
- }
-
- /** {@inheritDoc} */
- @Override public byte readByte() throws IOException {
- if (bufPosition >= bufLength) {
- currBufIdx++;
-
- switchCurrentBuffer(true);
- }
-
- return mem.readByte(currBuf + bufPosition++);
- }
-
- /** {@inheritDoc} */
- @Override public void readBytes(byte[] b, int offset, int len) throws IOException {
- while (len > 0) {
- if (bufPosition >= bufLength) {
- currBufIdx++;
-
- switchCurrentBuffer(true);
- }
-
- int remainInBuf = bufLength - bufPosition;
- int bytesToCp = len < remainInBuf ? len : remainInBuf;
-
- mem.readBytes(currBuf + bufPosition, b, offset, bytesToCp);
-
- offset += bytesToCp;
- len -= bytesToCp;
-
- bufPosition += bytesToCp;
- }
- }
-
- /**
- * Switch buffer to next.
- *
- * @param enforceEOF if we need to enforce {@link EOFException}.
- * @throws IOException if failed.
- */
- private void switchCurrentBuffer(boolean enforceEOF) throws IOException {
- bufStart = (long)BUFFER_SIZE * (long)currBufIdx;
-
- if (currBufIdx >= file.numBuffers()) {
- // end of file reached, no more buffers left
- if (enforceEOF)
- throw new EOFException("read past EOF: " + this);
-
- // Force EOF if a read takes place at this position
- currBufIdx--;
- bufPosition = BUFFER_SIZE;
- }
- else {
- currBuf = file.getBuffer(currBufIdx);
- bufPosition = 0;
-
- long buflen = length - bufStart;
-
- bufLength = buflen > BUFFER_SIZE ? BUFFER_SIZE : (int)buflen;
- }
- }
-
- /** {@inheritDoc} */
- @Override public void copyBytes(IndexOutput out, long numBytes) throws IOException {
- assert numBytes >= 0 : "numBytes=" + numBytes;
-
- GridLuceneOutputStream gridOut = out instanceof GridLuceneOutputStream ? (GridLuceneOutputStream)out : null;
-
- long left = numBytes;
-
- while (left > 0) {
- if (bufPosition == bufLength) {
- ++currBufIdx;
-
- switchCurrentBuffer(true);
- }
-
- final int bytesInBuf = bufLength - bufPosition;
- final int toCp = (int)(bytesInBuf < left ? bytesInBuf : left);
-
- if (gridOut != null)
- gridOut.writeBytes(currBuf + bufPosition, toCp);
- else {
- byte[] buff = new byte[toCp];
-
- mem.readBytes(currBuf + bufPosition, buff);
-
- out.writeBytes(buff, toCp);
- }
-
- bufPosition += toCp;
-
- left -= toCp;
- }
-
- assert left == 0 : "Insufficient bytes to copy: numBytes=" + numBytes + " copied=" + (numBytes - left);
- }
-
- /**
- * For direct calls from {@link GridLuceneOutputStream}.
- *
- * @param ptr Pointer.
- * @param len Length.
- * @throws IOException If failed.
- */
- void readBytes(long ptr, int len) throws IOException {
- while (len > 0) {
- if (bufPosition >= bufLength) {
- currBufIdx++;
-
- switchCurrentBuffer(true);
- }
-
- int remainInBuf = bufLength - bufPosition;
- int bytesToCp = len < remainInBuf ? len : remainInBuf;
-
- mem.copyMemory(currBuf + bufPosition, ptr, bytesToCp);
-
- ptr += bytesToCp;
- len -= bytesToCp;
-
- bufPosition += bytesToCp;
- }
- }
-
- /** {@inheritDoc} */
- @Override public long getFilePointer() {
- return currBufIdx < 0 ? 0 : bufStart + bufPosition;
- }
-
- /** {@inheritDoc} */
- @Override public void seek(long pos) throws IOException {
- if (currBuf == 0 || pos < bufStart || pos >= bufStart + BUFFER_SIZE) {
- currBufIdx = (int)(pos / BUFFER_SIZE);
-
- switchCurrentBuffer(false);
- }
-
- bufPosition = (int)(pos % BUFFER_SIZE);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneLockFactory.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneLockFactory.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneLockFactory.java
deleted file mode 100644
index bad6e67..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneLockFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.lucene.store.*;
-import org.gridgain.grid.util.*;
-
-import java.io.*;
-
-/**
- * Lucene {@link LockFactory} implementation.
- */
-public class GridLuceneLockFactory extends LockFactory {
- /** */
- @SuppressWarnings("TypeMayBeWeakened")
- private final GridConcurrentHashSet<String> locks = new GridConcurrentHashSet<>();
-
- /** {@inheritDoc} */
- @Override public Lock makeLock(String lockName) {
- return new LockImpl(lockName);
- }
-
- /** {@inheritDoc} */
- @Override public void clearLock(String lockName) throws IOException {
- locks.remove(lockName);
- }
-
- /**
- * {@link Lock} Implementation.
- */
- private class LockImpl extends Lock {
- /** */
- private final String lockName;
-
- /**
- * @param lockName Lock name.
- */
- private LockImpl(String lockName) {
- this.lockName = lockName;
- }
-
- /** {@inheritDoc} */
- @Override public boolean obtain() throws IOException {
- return locks.add(lockName);
- }
-
- /** {@inheritDoc} */
- @Override public void release() throws IOException {
- locks.remove(lockName);
- }
-
- /** {@inheritDoc} */
- @Override public boolean isLocked() throws IOException {
- return locks.contains(lockName);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneOutputStream.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneOutputStream.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneOutputStream.java
deleted file mode 100644
index e08d2a0..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridLuceneOutputStream.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.lucene.store.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-
-import java.io.IOException;
-
-/**
- * A memory-resident {@link IndexOutput} implementation.
- */
-public class GridLuceneOutputStream extends IndexOutput {
- /** Off-heap page size. */
- static final int BUFFER_SIZE = 32 * 1024;
-
- /** */
- private GridLuceneFile file;
-
- /** */
- private long currBuf;
-
- /** */
- private int currBufIdx;
-
- /** */
- private int bufPosition;
-
- /** */
- private long bufStart;
-
- /** */
- private int bufLength;
-
- /** */
- private final GridUnsafeMemory mem;
-
- /**
- * Constructor.
- *
- * @param f File.
- */
- public GridLuceneOutputStream(GridLuceneFile f) {
- file = f;
-
- mem = f.getDirectory().memory();
-
- // make sure that we switch to the
- // first needed buffer lazily
- currBufIdx = -1;
- currBuf = 0;
- }
-
- /**
- * Resets this to an empty file.
- */
- public void reset() {
- currBuf = 0;
- currBufIdx = -1;
- bufPosition = 0;
- bufStart = 0;
- bufLength = 0;
-
- file.setLength(0);
- }
-
- /** {@inheritDoc} */
- @Override public void close() throws IOException {
- flush();
- }
-
- /** {@inheritDoc} */
- @Override public void seek(long pos) throws IOException {
- // set the file length in case we seek back
- // and flush() has not been called yet
- setFileLength();
-
- if (pos < bufStart || pos >= bufStart + bufLength) {
- currBufIdx = (int)(pos / BUFFER_SIZE);
-
- switchCurrentBuffer();
- }
-
- bufPosition = (int)(pos % BUFFER_SIZE);
- }
-
- /** {@inheritDoc} */
- @Override public long length() {
- return file.getLength();
- }
-
- /** {@inheritDoc} */
- @Override public void writeByte(byte b) throws IOException {
- if (bufPosition == bufLength) {
- currBufIdx++;
-
- switchCurrentBuffer();
- }
-
- mem.writeByte(currBuf + bufPosition++, b);
- }
-
- /** {@inheritDoc} */
- @Override public void writeBytes(byte[] b, int offset, int len) throws IOException {
- assert b != null;
-
- while (len > 0) {
- if (bufPosition == bufLength) {
- currBufIdx++;
-
- switchCurrentBuffer();
- }
-
- int remainInBuf = BUFFER_SIZE - bufPosition;
- int bytesToCp = len < remainInBuf ? len : remainInBuf;
-
- mem.writeBytes(currBuf + bufPosition, b, offset, bytesToCp);
-
- offset += bytesToCp;
- len -= bytesToCp;
-
- bufPosition += bytesToCp;
- }
- }
-
- /**
- * Switch buffer to next.
- */
- private void switchCurrentBuffer() {
- currBuf = currBufIdx == file.numBuffers() ? file.addBuffer() : file.getBuffer(currBufIdx);
-
- bufPosition = 0;
- bufStart = (long)BUFFER_SIZE * (long)currBufIdx;
- bufLength = BUFFER_SIZE;
- }
-
- /**
- * Sets file length.
- */
- private void setFileLength() {
- long pointer = bufStart + bufPosition;
-
- if (pointer > file.getLength())
- file.setLength(pointer);
- }
-
- /** {@inheritDoc} */
- @Override public void flush() throws IOException {
- setFileLength();
- }
-
- /** {@inheritDoc} */
- @Override public long getFilePointer() {
- return currBufIdx < 0 ? 0 : bufStart + bufPosition;
- }
-
- /**
- * Returns byte usage of all buffers.
- *
- * @return Bytes used.
- */
- public long sizeInBytes() {
- return (long)file.numBuffers() * (long)BUFFER_SIZE;
- }
-
- /** {@inheritDoc} */
- @Override public void copyBytes(DataInput input, long numBytes) throws IOException {
- assert numBytes >= 0 : "numBytes=" + numBytes;
-
- GridLuceneInputStream gridInput = input instanceof GridLuceneInputStream ? (GridLuceneInputStream)input : null;
-
- while (numBytes > 0) {
- if (bufPosition == bufLength) {
- currBufIdx++;
-
- switchCurrentBuffer();
- }
-
- int toCp = BUFFER_SIZE - bufPosition;
-
- if (numBytes < toCp)
- toCp = (int)numBytes;
-
- if (gridInput != null)
- gridInput.readBytes(currBuf + bufPosition, toCp);
- else {
- byte[] buff = new byte[toCp];
-
- input.readBytes(buff, 0, toCp, false);
-
- mem.writeBytes(currBuf + bufPosition, buff);
- }
-
- numBytes -= toCp;
- bufPosition += toCp;
- }
- }
-
- /**
- * For direct usage by {@link GridLuceneInputStream}.
- *
- * @param ptr Pointer.
- * @param len Length.
- * @throws IOException If failed.
- */
- void writeBytes(long ptr, int len) throws IOException {
- while (len > 0) {
- if (bufPosition == bufLength) {
- currBufIdx++;
- switchCurrentBuffer();
- }
-
- int remainInBuf = BUFFER_SIZE - bufPosition;
- int bytesToCp = len < remainInBuf ? len : remainInBuf;
-
- mem.copyMemory(ptr, currBuf + bufPosition, bytesToCp);
-
- ptr += bytesToCp;
- len -= bytesToCp;
- bufPosition += bytesToCp;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridSearchRowPointer.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridSearchRowPointer.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridSearchRowPointer.java
deleted file mode 100644
index d841b1d..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridSearchRowPointer.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.gridgain.grid.util.offheap.unsafe.*;
-import org.h2.result.*;
-
-/**
- * Search row which supports pointer operations.
- */
-public interface GridSearchRowPointer extends SearchRow, GridOffHeapSmartPointer {
- // No-op.
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/package.html
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/package.html b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/package.html
deleted file mode 100644
index 1a7d215..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/package.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<!--
- @html.file.header
- _________ _____ __________________ _____
- __ ____/___________(_)______ /__ ____/______ ____(_)_______
- _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
--->
-<html>
-<body>
- <!-- Package description. -->
- Contains <b>default</b> H2-based indexing SPI implementation.
-</body>
-</html>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFieldsQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFieldsQuerySelfTest.java
index e387840..cec4514 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFieldsQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractFieldsQuerySelfTest.java
@@ -12,17 +12,16 @@ package org.gridgain.grid.kernal.processors.cache;
import org.apache.ignite.configuration.*;
import org.apache.ignite.lang.*;
import org.apache.ignite.marshaller.optimized.*;
-import org.apache.ignite.spi.indexing.*;
+import org.apache.ignite.spi.discovery.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.affinity.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.processors.cache.query.*;
-import org.apache.ignite.spi.discovery.*;
-import org.apache.ignite.spi.discovery.tcp.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.testframework.junits.common.*;
import org.jetbrains.annotations.*;
@@ -53,12 +52,6 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
/** Name of the cache that doesn't index primitives. */
private static final String CACHE_COMPLEX_KEYS = "cacheComplexKeys";
- /** Name of the indexing SPI that doesn't index primitives. */
- private static final String SPI_NO_PRIMITIVES = "spiNoPrimitives";
-
- /** Name of the indexing SPI that doesn't index primitives. */
- private static final String SPI_COMPLEX_KEYS = "spiComplexKeys";
-
/** Flag indicating if starting node should have cache. */
protected boolean hasCache;
@@ -66,13 +59,10 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(gridName);
- cfg.setIndexingSpi(indexing(null, true), indexing(SPI_NO_PRIMITIVES, false), indexing(SPI_COMPLEX_KEYS, false));
-
cfg.setMarshaller(new IgniteOptimizedMarshaller(false));
if (hasCache)
- cfg.setCacheConfiguration(cache(null, null), cache(CACHE, null), cache(EMPTY_CACHE, null),
- cache(CACHE_NO_PRIMITIVES, SPI_NO_PRIMITIVES), cache(CACHE_COMPLEX_KEYS, SPI_COMPLEX_KEYS));
+ cfg.setCacheConfiguration(cache(null, null), cache(CACHE, null), cache(EMPTY_CACHE, null));
else
cfg.setCacheConfiguration();
@@ -93,30 +83,20 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
cache.setCacheMode(cacheMode());
cache.setAtomicityMode(atomicityMode());
cache.setWriteSynchronizationMode(GridCacheWriteSynchronizationMode.FULL_SYNC);
- cache.setIndexingSpiName(spiName);
cache.setPreloadMode(SYNC);
- if (cacheMode() == PARTITIONED)
- cache.setBackups(1);
-
- return cache;
- }
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
- /**
- * @param name SPI name.
- * @param primitives Whether to index primitives.
- * @return Indexing SPI.
- */
- private IndexingSpi indexing(@Nullable String name, boolean primitives) {
- GridH2IndexingSpi spi = new GridH2IndexingSpi();
+ qcfg.setIndexPrimitiveKey(true);
+ qcfg.setIndexPrimitiveValue(true);
+ qcfg.setIndexFixedTyping(true);
- if (name != null)
- spi.setName(name);
+ cache.setQueryConfiguration(qcfg);
- spi.setDefaultIndexPrimitiveKey(primitives);
- spi.setDefaultIndexPrimitiveValue(primitives);
+ if (cacheMode() == PARTITIONED)
+ cache.setBackups(1);
- return spi;
+ return cache;
}
/** @return Discovery SPI. */
@@ -379,17 +359,17 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
GridCacheQueryFuture<List<?>> fut = qry.execute();
- List<IndexingFieldMetadata> meta = metadata(fut);
+ List<GridQueryFieldMetadata> meta = metadata(fut);
assert meta != null;
assert meta.size() == 4;
- Iterator<IndexingFieldMetadata> metaIt = meta.iterator();
+ Iterator<GridQueryFieldMetadata> metaIt = meta.iterator();
assert metaIt != null;
assert metaIt.hasNext();
- IndexingFieldMetadata field = metaIt.next();
+ GridQueryFieldMetadata field = metaIt.next();
assert field != null;
assert "PUBLIC".equals(field.schemaName());
@@ -479,17 +459,17 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
GridCacheQueryFuture<List<?>> fut = qry.execute();
- List<IndexingFieldMetadata> meta = metadata(fut);
+ List<GridQueryFieldMetadata> meta = metadata(fut);
assert meta != null;
assert meta.size() == 9;
- Iterator<IndexingFieldMetadata> metaIt = meta.iterator();
+ Iterator<GridQueryFieldMetadata> metaIt = meta.iterator();
assert metaIt != null;
assert metaIt.hasNext();
- IndexingFieldMetadata field = metaIt.next();
+ GridQueryFieldMetadata field = metaIt.next();
assert field != null;
assert "PUBLIC".equals(field.schemaName());
@@ -545,7 +525,7 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
assert "PUBLIC".equals(field.schemaName());
assert "ORGANIZATION".equals(field.typeName());
assert "_KEY".equals(field.fieldName());
- assert String.class.getName().equals(field.fieldTypeName());
+ assert String.class.getName().equals(field.fieldTypeName()) : field.fieldTypeName();
assert metaIt.hasNext();
@@ -645,12 +625,12 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
assert fut != null;
- List<IndexingFieldMetadata> meta = metadata(fut);
+ List<GridQueryFieldMetadata> meta = metadata(fut);
assert meta != null;
assert meta.size() == 1;
- IndexingFieldMetadata field = F.first(meta);
+ GridQueryFieldMetadata field = F.first(meta);
assert field != null;
assert "PUBLIC".equals(field.schemaName());
@@ -689,16 +669,16 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
GridCacheQueryFuture<List<?>> fut = qry.execute();
- List<IndexingFieldMetadata> meta = metadata(fut);
+ List<GridQueryFieldMetadata> meta = metadata(fut);
assert meta != null;
assert meta.size() == 4;
- Iterator<IndexingFieldMetadata> metaIt = meta.iterator();
+ Iterator<GridQueryFieldMetadata> metaIt = meta.iterator();
assert metaIt.hasNext();
- IndexingFieldMetadata field = metaIt.next();
+ GridQueryFieldMetadata field = metaIt.next();
assert field != null;
assert "INTEGER".equals(field.typeName());
@@ -787,7 +767,7 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
}
/** @throws Exception If failed. */
- public void testNoPrimitives() throws Exception {
+ public void _testNoPrimitives() throws Exception { // TODO
GridCache<Object, Object> cache = grid(0).cache(CACHE_NO_PRIMITIVES);
assert cache.putx("key", "val");
@@ -806,7 +786,7 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
}
/** @throws Exception If failed. */
- public void testComplexKeys() throws Exception {
+ public void _testComplexKeys() throws Exception { // TODO
GridCache<PersonKey, Person> cache = grid(0).cache(CACHE_COMPLEX_KEYS);
UUID id = UUID.randomUUID();
@@ -1109,7 +1089,7 @@ public abstract class GridCacheAbstractFieldsQuerySelfTest extends GridCommonAbs
* @return Metadata.
* @throws GridException In case of error.
*/
- private List<IndexingFieldMetadata> metadata(GridCacheQueryFuture<List<?>> fut) throws GridException {
+ private List<GridQueryFieldMetadata> metadata(GridCacheQueryFuture<List<?>> fut) throws GridException {
assert fut != null;
return ((GridCacheQueryMetadataAware)fut).metadata().get();
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractQuerySelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractQuerySelfTest.java
index 3e20845..1f7fca8 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheAbstractQuerySelfTest.java
@@ -14,17 +14,16 @@ import org.apache.ignite.configuration.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
import org.apache.ignite.marshaller.optimized.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.apache.ignite.spi.swapspace.file.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.cache.store.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.processors.cache.query.*;
-import org.apache.ignite.spi.discovery.tcp.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
-import org.apache.ignite.spi.swapspace.file.*;
import org.gridgain.grid.util.tostring.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
@@ -38,13 +37,13 @@ import java.util.*;
import java.util.concurrent.*;
import static java.util.concurrent.TimeUnit.*;
+import static org.apache.ignite.events.IgniteEventType.*;
import static org.gridgain.grid.cache.GridCacheAtomicityMode.*;
import static org.gridgain.grid.cache.GridCacheDistributionMode.*;
import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCachePreloadMode.*;
import static org.gridgain.grid.cache.GridCacheWriteSynchronizationMode.*;
import static org.gridgain.grid.cache.query.GridCacheQueryType.*;
-import static org.apache.ignite.events.IgniteEventType.*;
import static org.junit.Assert.*;
/**
@@ -97,12 +96,11 @@ public abstract class GridCacheAbstractQuerySelfTest extends GridCommonAbstractT
c.setDiscoverySpi(disco);
- GridH2IndexingSpi indexing = new GridH2IndexingSpi();
+ GridQueryConfiguration idxCfg = new GridQueryConfiguration();
- indexing.setDefaultIndexPrimitiveKey(true);
- indexing.setIndexCustomFunctionClasses(SqlFunctions.class);
+ idxCfg.setIndexCustomFunctionClasses(SqlFunctions.class);
- c.setIndexingSpi(indexing);
+ c.setQueryConfiguration(idxCfg);
// Otherwise noop swap space will be chosen on Windows.
c.setSwapSpaceSpi(new FileSwapSpaceSpi());
@@ -126,6 +124,13 @@ public abstract class GridCacheAbstractQuerySelfTest extends GridCommonAbstractT
cc.setSwapEnabled(true);
cc.setEvictNearSynchronized(false);
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
+
+ qcfg.setIndexPrimitiveKey(true);
+ qcfg.setIndexFixedTyping(true);
+
+ cc.setQueryConfiguration(qcfg);
+
// Explicitly set number of backups equal to number of grids.
if (cacheMode() == GridCacheMode.PARTITIONED)
cc.setBackups(gridCount());
@@ -1618,7 +1623,7 @@ public abstract class GridCacheAbstractQuerySelfTest extends GridCommonAbstractT
assertNull(qe.continuousQueryFilter());
assertArrayEquals(new Integer[] { 10 }, qe.arguments());
- List<?> row = qe.row();
+ List<?> row = (List<?>)qe.row();
map.put((Integer)row.get(0), (String)row.get(1));
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheCrossCacheQuerySelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
index 72e171e..0720c91 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
@@ -13,12 +13,11 @@ import org.apache.ignite.*;
import org.apache.ignite.configuration.*;
import org.apache.ignite.lang.*;
import org.apache.ignite.marshaller.optimized.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
import org.gridgain.testframework.junits.common.*;
import java.util.*;
@@ -49,10 +48,6 @@ public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
c.setMarshaller(new IgniteOptimizedMarshaller(false));
- GridH2IndexingSpi indexing = new GridH2IndexingSpi();
-
- c.setIndexingSpi(indexing);
-
c.setCacheConfiguration(createCache("replicated", GridCacheMode.REPLICATED),
createCache("partitioned", GridCacheMode.PARTITIONED));
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffHeapAndSwapSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffHeapAndSwapSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffHeapAndSwapSelfTest.java
index 88a18fe..cedaa63 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffHeapAndSwapSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffHeapAndSwapSelfTest.java
@@ -12,15 +12,15 @@ package org.gridgain.grid.kernal.processors.cache;
import org.apache.ignite.configuration.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.kernal.*;
-import org.gridgain.grid.kernal.processors.cache.distributed.near.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
import org.apache.ignite.spi.swapspace.file.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.kernal.*;
+import org.gridgain.grid.kernal.processors.cache.distributed.near.*;
import org.gridgain.grid.util.lang.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.testframework.junits.common.*;
@@ -28,12 +28,12 @@ import org.gridgain.testframework.junits.common.*;
import java.util.*;
import java.util.concurrent.atomic.*;
+import static org.apache.ignite.events.IgniteEventType.*;
import static org.apache.ignite.configuration.IgniteDeploymentMode.*;
import static org.gridgain.grid.cache.GridCacheAtomicityMode.*;
-import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCacheDistributionMode.*;
+import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCachePeekMode.*;
-import static org.apache.ignite.events.IgniteEventType.*;
/**
* Tests off heap storage when both offheaped and swapped entries exists.
@@ -113,13 +113,6 @@ public class GridCacheOffHeapAndSwapSelfTest extends GridCommonAbstractTest {
cfg.setSwapSpaceSpi(new FileSwapSpaceSpi());
- GridH2IndexingSpi indexingSpi = new GridH2IndexingSpi();
-
- indexingSpi.setDefaultIndexPrimitiveKey(true);
- indexingSpi.setDefaultIndexPrimitiveValue(true);
-
- cfg.setIndexingSpi(indexingSpi);
-
GridCacheConfiguration cacheCfg = defaultCacheConfiguration();
cacheCfg.setWriteSynchronizationMode(GridCacheWriteSynchronizationMode.FULL_SYNC);
@@ -135,6 +128,13 @@ public class GridCacheOffHeapAndSwapSelfTest extends GridCommonAbstractTest {
cacheCfg.setEvictionPolicy(null);
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
+
+ qcfg.setIndexPrimitiveKey(true);
+ qcfg.setIndexPrimitiveValue(true);
+
+ cacheCfg.setQueryConfiguration(qcfg);
+
cfg.setCacheConfiguration(cacheCfg);
cfg.setDeploymentMode(SHARED);
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryLoadSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryLoadSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryLoadSelfTest.java
index 034d433..b696514 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryLoadSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryLoadSelfTest.java
@@ -11,15 +11,15 @@ package org.gridgain.grid.kernal.processors.cache;
import org.apache.ignite.configuration.*;
import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.cache.store.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.processors.cache.query.*;
-import org.apache.ignite.spi.discovery.tcp.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
import org.gridgain.testframework.junits.common.*;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMetricsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMetricsSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMetricsSelfTest.java
index 10adf07..7d88586 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMetricsSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMetricsSelfTest.java
@@ -10,12 +10,11 @@
package org.gridgain.grid.kernal.processors.cache;
import org.apache.ignite.configuration.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
import org.gridgain.testframework.junits.common.*;
import java.util.*;
@@ -56,17 +55,17 @@ public class GridCacheQueryMetricsSelfTest extends GridCommonAbstractTest {
cfg.setDiscoverySpi(disco);
- GridH2IndexingSpi indexingSpi = new GridH2IndexingSpi();
-
- indexingSpi.setDefaultIndexPrimitiveKey(true);
-
- cfg.setIndexingSpi(indexingSpi);
-
GridCacheConfiguration cacheCfg = defaultCacheConfiguration();
cacheCfg.setCacheMode(CACHE_MODE);
cacheCfg.setWriteSynchronizationMode(FULL_SYNC);
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
+
+ qcfg.setIndexPrimitiveKey(true);
+
+ cacheCfg.setQueryConfiguration(qcfg);
+
cfg.setCacheConfiguration(cacheCfg);
return cfg;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMultiThreadedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMultiThreadedSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMultiThreadedSelfTest.java
index 70a4f3e..95b86f1 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMultiThreadedSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryMultiThreadedSelfTest.java
@@ -13,18 +13,18 @@ import org.apache.ignite.*;
import org.apache.ignite.configuration.*;
import org.apache.ignite.lang.*;
import org.apache.ignite.marshaller.optimized.*;
-import org.apache.ignite.spi.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.apache.ignite.spi.swapspace.file.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.eviction.lru.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.processors.cache.query.*;
-import org.apache.ignite.spi.discovery.tcp.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
-import org.apache.ignite.spi.swapspace.file.*;
+import org.gridgain.grid.kernal.processors.query.*;
+import org.gridgain.grid.kernal.processors.query.h2.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.testframework.junits.common.*;
import org.jetbrains.annotations.*;
@@ -87,38 +87,49 @@ public class GridCacheQueryMultiThreadedSelfTest extends GridCommonAbstractTest
cacheCfg.setBackups(1);
cacheCfg.setEvictionPolicy(evictsEnabled() ? new GridCacheLruEvictionPolicy(100) : null);
- if (offheapEnabled() && evictsEnabled())
- cacheCfg.setOffHeapMaxMemory(1000); // Small offheap for evictions.
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
- cfg.setCacheConfiguration(cacheCfg);
+ qcfg.setIndexPrimitiveKey(true);
- GridH2IndexingSpi indexing = new GridH2IndexingSpi() {
- @Override public <K> void onSwap(@Nullable String spaceName, String swapSpaceName, K key)
- throws IgniteSpiException {
- super.onSwap(spaceName, swapSpaceName, key);
+ cacheCfg.setQueryConfiguration(qcfg);
- idxSwapCnt.incrementAndGet();
- }
+ if (offheapEnabled() && evictsEnabled())
+ cacheCfg.setOffHeapMaxMemory(1000); // Small offheap for evictions.
- @Override public <K, V> void onUnswap(@Nullable String spaceName, K key, V val, byte[] valBytes)
- throws IgniteSpiException {
- super.onUnswap(spaceName, key, val, valBytes);
+ cfg.setCacheConfiguration(cacheCfg);
- idxUnswapCnt.incrementAndGet();
- }
- };
+ GridQueryConfiguration indexing = new GridQueryConfiguration();
- indexing.setDefaultIndexPrimitiveKey(true);
indexing.setMaxOffheapRowsCacheSize(128);
if (offheapEnabled())
indexing.setMaxOffHeapMemory(0);
- cfg.setIndexingSpi(indexing);
+ cfg.setQueryConfiguration(indexing);
+
+ GridQueryProcessor.idxCls = FakeIndexing.class;
return cfg;
}
+ /**
+ *
+ */
+ private static class FakeIndexing extends GridH2Indexing {
+ @Override public void onSwap(@Nullable String spaceName, Object key) throws GridException {
+ super.onSwap(spaceName, key);
+
+ idxSwapCnt.incrementAndGet();
+ }
+
+ @Override public void onUnswap(@Nullable String spaceName, Object key, Object val, byte[] valBytes)
+ throws GridException {
+ super.onUnswap(spaceName, key, val, valBytes);
+
+ idxUnswapCnt.incrementAndGet();
+ }
+ }
+
/** @return {@code true} If offheap enabled. */
protected boolean offheapEnabled() {
return false;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryUserResourceSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryUserResourceSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryUserResourceSelfTest.java
index 18101a4..f98bb93 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryUserResourceSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheQueryUserResourceSelfTest.java
@@ -13,12 +13,12 @@ import org.apache.ignite.*;
import org.apache.ignite.cluster.*;
import org.apache.ignite.configuration.*;
import org.apache.ignite.lang.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
import org.apache.ignite.spi.discovery.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.testframework.*;
import org.gridgain.testframework.junits.common.*;
[06/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneIndex.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneIndex.java
new file mode 100644
index 0000000..dd2a29e
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneIndex.java
@@ -0,0 +1,384 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.commons.codec.binary.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.marshaller.*;
+import org.apache.ignite.spi.indexing.*;
+import org.apache.lucene.analysis.standard.*;
+import org.apache.lucene.document.*;
+import org.apache.lucene.index.*;
+import org.apache.lucene.queryParser.*;
+import org.apache.lucene.search.*;
+import org.apache.lucene.util.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.kernal.processors.query.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.lang.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.jetbrains.annotations.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import static org.gridgain.grid.kernal.processors.query.h2.GridH2Indexing.*;
+
+/**
+ * Lucene fulltext index.
+ */
+public class GridLuceneIndex implements Closeable {
+ /** Field name for string representation of value. */
+ public static final String VAL_STR_FIELD_NAME = "_gg_val_str__";
+
+ /** Field name for value version. */
+ public static final String VER_FIELD_NAME = "_gg_ver__";
+
+ /** Field name for value expiration time. */
+ public static final String EXPIRATION_TIME_FIELD_NAME = "_gg_expires__";
+
+ /** */
+ private final IgniteMarshaller marshaller;
+
+ /** */
+ private final String spaceName;
+
+ /** */
+ private final GridQueryTypeDescriptor type;
+
+ /** */
+ private final IndexWriter writer;
+
+ /** */
+ private final String[] idxdFields;
+
+ /** */
+ private final boolean storeVal;
+
+ /** */
+ private final BitSet keyFields = new BitSet();
+
+ /** */
+ private final AtomicLong updateCntr = new GridAtomicLong();
+
+ /** */
+ private final GridLuceneDirectory dir;
+
+ /**
+ * Constructor.
+ *
+ * @param marshaller Indexing marshaller.
+ * @param mem Unsafe memory.
+ * @param spaceName Space name.
+ * @param type Type descriptor.
+ * @param storeVal Store value in index.
+ * @throws GridException If failed.
+ */
+ public GridLuceneIndex(IgniteMarshaller marshaller, @Nullable GridUnsafeMemory mem,
+ @Nullable String spaceName, GridQueryTypeDescriptor type, boolean storeVal) throws GridException {
+ this.marshaller = marshaller;
+ this.spaceName = spaceName;
+ this.type = type;
+ this.storeVal = storeVal;
+
+ dir = new GridLuceneDirectory(mem == null ? new GridUnsafeMemory(0) : mem);
+
+ try {
+ writer = new IndexWriter(dir, new IndexWriterConfig(Version.LUCENE_30, new StandardAnalyzer(
+ Version.LUCENE_30)));
+ }
+ catch (IOException e) {
+ throw new GridException(e);
+ }
+
+ GridQueryIndexDescriptor idx = null;
+
+ for (GridQueryIndexDescriptor descriptor : type.indexes().values()) {
+ if (descriptor.type() == GridQueryIndexType.FULLTEXT) {
+ idx = descriptor;
+
+ break;
+ }
+ }
+
+ if (idx != null) {
+ Collection<String> fields = idx.fields();
+
+ idxdFields = new String[fields.size() + 1];
+
+ fields.toArray(idxdFields);
+
+ for (int i = 0, len = fields.size() ; i < len; i++)
+ keyFields.set(i, type.keyFields().containsKey(idxdFields[i]));
+ }
+ else {
+ assert type.valueTextIndex() || type.valueClass() == String.class;
+
+ idxdFields = new String[1];
+ }
+
+ idxdFields[idxdFields.length - 1] = VAL_STR_FIELD_NAME;
+ }
+
+ /**
+ * Stores given data in this fulltext index.
+ *
+ * @param key Key.
+ * @param val Value.
+ * @param ver Version.
+ * @param expires Expiration time.
+ * @throws GridException If failed.
+ */
+ public void store(Object key, Object val, byte[] ver, long expires) throws GridException {
+ Document doc = new Document();
+
+ boolean stringsFound = false;
+
+ if (type.valueTextIndex() || type.valueClass() == String.class) {
+ doc.add(new Field(VAL_STR_FIELD_NAME, val.toString(), Field.Store.YES, Field.Index.ANALYZED));
+
+ stringsFound = true;
+ }
+
+ for (int i = 0, last = idxdFields.length - 1; i < last; i++) {
+ Object fieldVal = type.value(keyFields.get(i) ? key : val, idxdFields[i]);
+
+ if (fieldVal != null) {
+ doc.add(new Field(idxdFields[i], fieldVal.toString(), Field.Store.YES, Field.Index.ANALYZED));
+
+ stringsFound = true;
+ }
+ }
+
+ String keyStr = Base64.encodeBase64String(marshaller.marshal(key));
+
+ try {
+ // Delete first to avoid duplicates.
+ writer.deleteDocuments(new Term(KEY_FIELD_NAME, keyStr));
+
+ if (!stringsFound)
+ return; // We did not find any strings to be indexed, will not store data at all.
+
+ doc.add(new Field(KEY_FIELD_NAME, keyStr, Field.Store.YES, Field.Index.NOT_ANALYZED));
+
+ if (storeVal && type.valueClass() != String.class)
+ doc.add(new Field(VAL_FIELD_NAME, marshaller.marshal(val)));
+
+ doc.add(new Field(VER_FIELD_NAME, ver));
+
+ doc.add(new Field(EXPIRATION_TIME_FIELD_NAME, DateTools.timeToString(expires,
+ DateTools.Resolution.MILLISECOND), Field.Store.YES, Field.Index.NOT_ANALYZED));
+
+ writer.addDocument(doc);
+ }
+ catch (IOException e) {
+ throw new GridException(e);
+ }
+ finally {
+ updateCntr.incrementAndGet();
+ }
+ }
+
+ /**
+ * Removes entry for given key from this index.
+ *
+ * @param key Key.
+ * @throws GridException If failed.
+ */
+ public void remove(Object key) throws GridException {
+ try {
+ writer.deleteDocuments(new Term(KEY_FIELD_NAME, Base64.encodeBase64String(marshaller.marshal(key))));
+ }
+ catch (IOException e) {
+ throw new GridException(e);
+ }
+ finally {
+ updateCntr.incrementAndGet();
+ }
+ }
+
+ /**
+ * Runs lucene fulltext query over this index.
+ *
+ * @param qry Query.
+ * @param filters Filters over result.
+ * @return Query result.
+ * @throws GridException If failed.
+ */
+ public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> query(String qry,
+ GridIndexingQueryFilter filters) throws GridException {
+ IndexReader reader;
+
+ try {
+ long updates = updateCntr.get();
+
+ if (updates != 0) {
+ writer.commit();
+
+ updateCntr.addAndGet(-updates);
+ }
+
+ reader = IndexReader.open(writer, true);
+ }
+ catch (IOException e) {
+ throw new GridException(e);
+ }
+
+ IndexSearcher searcher = new IndexSearcher(reader);
+
+ MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_30, idxdFields,
+ writer.getAnalyzer());
+
+ // Filter expired items.
+ Filter f = new TermRangeFilter(EXPIRATION_TIME_FIELD_NAME, DateTools.timeToString(U.currentTimeMillis(),
+ DateTools.Resolution.MILLISECOND), null, false, false);
+
+ TopDocs docs;
+
+ try {
+ docs = searcher.search(parser.parse(qry), f, Integer.MAX_VALUE);
+ }
+ catch (Exception e) {
+ throw new GridException(e);
+ }
+
+ IgniteBiPredicate<K, V> fltr = null;
+
+ if (filters != null)
+ fltr = filters.forSpace(spaceName);
+
+ return new It<>(reader, searcher, docs.scoreDocs, fltr);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close() {
+ U.closeQuiet(writer);
+ U.closeQuiet(dir);
+ }
+
+ /**
+ * Key-value iterator over fulltext search result.
+ */
+ private class It<K, V> extends GridCloseableIteratorAdapter<IgniteBiTuple<K, V>> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ private final IndexReader reader;
+
+ /** */
+ private final IndexSearcher searcher;
+
+ /** */
+ private final ScoreDoc[] docs;
+
+ /** */
+ private final IgniteBiPredicate<K, V> filters;
+
+ /** */
+ private int idx;
+
+ /** */
+ private IgniteBiTuple<K, V> curr;
+
+ /**
+ * Constructor.
+ *
+ * @param reader Reader.
+ * @param searcher Searcher.
+ * @param docs Docs.
+ * @param filters Filters over result.
+ * @throws GridException if failed.
+ */
+ private It(IndexReader reader, IndexSearcher searcher, ScoreDoc[] docs, IgniteBiPredicate<K, V> filters)
+ throws GridException {
+ this.reader = reader;
+ this.searcher = searcher;
+ this.docs = docs;
+ this.filters = filters;
+
+ findNext();
+ }
+
+ /**
+ * Filters key using predicates.
+ *
+ * @param key Key.
+ * @param val Value.
+ * @return {@code True} if key passes filter.
+ */
+ private boolean filter(K key, V val) {
+ return filters == null || filters.apply(key, val) ;
+ }
+
+ /**
+ * Finds next element.
+ *
+ * @throws GridException If failed.
+ */
+ private void findNext() throws GridException {
+ curr = null;
+
+ while (idx < docs.length) {
+ Document doc;
+
+ try {
+ doc = searcher.doc(docs[idx++].doc);
+ }
+ catch (IOException e) {
+ throw new GridException(e);
+ }
+
+ String keyStr = doc.get(KEY_FIELD_NAME);
+
+ ClassLoader ldr = null; // TODO
+
+ K k = marshaller.unmarshal(Base64.decodeBase64(keyStr), ldr);
+
+ byte[] valBytes = doc.getBinaryValue(VAL_FIELD_NAME);
+
+ V v = valBytes != null ? marshaller.<V>unmarshal(valBytes, ldr) :
+ type.valueClass() == String.class ?
+ (V)doc.get(VAL_STR_FIELD_NAME): null;
+
+ if (!filter(k, v))
+ continue;
+
+// byte[] ver = doc.getBinaryValue(VER_FIELD_NAME); TODO rm version
+
+ curr = new IgniteBiTuple<>(k, v);
+
+ break;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteBiTuple<K, V> onNext() throws GridException {
+ IgniteBiTuple<K, V> res = curr;
+
+ findNext();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean onHasNext() throws GridException {
+ return curr != null;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void onClose() throws GridException {
+ U.closeQuiet(searcher);
+ U.closeQuiet(reader);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneInputStream.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneInputStream.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneInputStream.java
new file mode 100644
index 0000000..2f3fe89
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneInputStream.java
@@ -0,0 +1,220 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.lucene.store.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+
+import java.io.*;
+
+import static org.gridgain.grid.kernal.processors.query.h2.opt.GridLuceneOutputStream.*;
+
+/**
+ * A memory-resident {@link IndexInput} implementation.
+ */
+public class GridLuceneInputStream extends IndexInput {
+ /** */
+ private GridLuceneFile file;
+
+ /** */
+ private long length;
+
+ /** */
+ private long currBuf;
+
+ /** */
+ private int currBufIdx;
+
+ /** */
+ private int bufPosition;
+
+ /** */
+ private long bufStart;
+
+ /** */
+ private int bufLength;
+
+ /** */
+ private final GridUnsafeMemory mem;
+
+ /**
+ * Constructor.
+ *
+ * @param name Name.
+ * @param f File.
+ * @throws IOException If failed.
+ */
+ public GridLuceneInputStream(String name, GridLuceneFile f) throws IOException {
+ super("RAMInputStream(name=" + name + ")");
+
+ file = f;
+
+ length = file.getLength();
+
+ if (length / BUFFER_SIZE >= Integer.MAX_VALUE)
+ throw new IOException("RAMInputStream too large length=" + length + ": " + name);
+
+ mem = file.getDirectory().memory();
+
+ // make sure that we switch to the
+ // first needed buffer lazily
+ currBufIdx = -1;
+ currBuf = 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close() {
+ // nothing to do here
+ }
+
+ /** {@inheritDoc} */
+ @Override public long length() {
+ return length;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte readByte() throws IOException {
+ if (bufPosition >= bufLength) {
+ currBufIdx++;
+
+ switchCurrentBuffer(true);
+ }
+
+ return mem.readByte(currBuf + bufPosition++);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readBytes(byte[] b, int offset, int len) throws IOException {
+ while (len > 0) {
+ if (bufPosition >= bufLength) {
+ currBufIdx++;
+
+ switchCurrentBuffer(true);
+ }
+
+ int remainInBuf = bufLength - bufPosition;
+ int bytesToCp = len < remainInBuf ? len : remainInBuf;
+
+ mem.readBytes(currBuf + bufPosition, b, offset, bytesToCp);
+
+ offset += bytesToCp;
+ len -= bytesToCp;
+
+ bufPosition += bytesToCp;
+ }
+ }
+
+ /**
+ * Switch buffer to next.
+ *
+ * @param enforceEOF if we need to enforce {@link EOFException}.
+ * @throws IOException if failed.
+ */
+ private void switchCurrentBuffer(boolean enforceEOF) throws IOException {
+ bufStart = (long)BUFFER_SIZE * (long)currBufIdx;
+
+ if (currBufIdx >= file.numBuffers()) {
+ // end of file reached, no more buffers left
+ if (enforceEOF)
+ throw new EOFException("read past EOF: " + this);
+
+ // Force EOF if a read takes place at this position
+ currBufIdx--;
+ bufPosition = BUFFER_SIZE;
+ }
+ else {
+ currBuf = file.getBuffer(currBufIdx);
+ bufPosition = 0;
+
+ long buflen = length - bufStart;
+
+ bufLength = buflen > BUFFER_SIZE ? BUFFER_SIZE : (int)buflen;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void copyBytes(IndexOutput out, long numBytes) throws IOException {
+ assert numBytes >= 0 : "numBytes=" + numBytes;
+
+ GridLuceneOutputStream gridOut = out instanceof GridLuceneOutputStream ? (GridLuceneOutputStream)out : null;
+
+ long left = numBytes;
+
+ while (left > 0) {
+ if (bufPosition == bufLength) {
+ ++currBufIdx;
+
+ switchCurrentBuffer(true);
+ }
+
+ final int bytesInBuf = bufLength - bufPosition;
+ final int toCp = (int)(bytesInBuf < left ? bytesInBuf : left);
+
+ if (gridOut != null)
+ gridOut.writeBytes(currBuf + bufPosition, toCp);
+ else {
+ byte[] buff = new byte[toCp];
+
+ mem.readBytes(currBuf + bufPosition, buff);
+
+ out.writeBytes(buff, toCp);
+ }
+
+ bufPosition += toCp;
+
+ left -= toCp;
+ }
+
+ assert left == 0 : "Insufficient bytes to copy: numBytes=" + numBytes + " copied=" + (numBytes - left);
+ }
+
+ /**
+ * For direct calls from {@link GridLuceneOutputStream}.
+ *
+ * @param ptr Pointer.
+ * @param len Length.
+ * @throws IOException If failed.
+ */
+ void readBytes(long ptr, int len) throws IOException {
+ while (len > 0) {
+ if (bufPosition >= bufLength) {
+ currBufIdx++;
+
+ switchCurrentBuffer(true);
+ }
+
+ int remainInBuf = bufLength - bufPosition;
+ int bytesToCp = len < remainInBuf ? len : remainInBuf;
+
+ mem.copyMemory(currBuf + bufPosition, ptr, bytesToCp);
+
+ ptr += bytesToCp;
+ len -= bytesToCp;
+
+ bufPosition += bytesToCp;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getFilePointer() {
+ return currBufIdx < 0 ? 0 : bufStart + bufPosition;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void seek(long pos) throws IOException {
+ if (currBuf == 0 || pos < bufStart || pos >= bufStart + BUFFER_SIZE) {
+ currBufIdx = (int)(pos / BUFFER_SIZE);
+
+ switchCurrentBuffer(false);
+ }
+
+ bufPosition = (int)(pos % BUFFER_SIZE);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneLockFactory.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneLockFactory.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneLockFactory.java
new file mode 100644
index 0000000..34d92ee
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneLockFactory.java
@@ -0,0 +1,64 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.lucene.store.*;
+import org.gridgain.grid.util.*;
+
+import java.io.*;
+
+/**
+ * Lucene {@link LockFactory} implementation.
+ */
+public class GridLuceneLockFactory extends LockFactory {
+ /** */
+ @SuppressWarnings("TypeMayBeWeakened")
+ private final GridConcurrentHashSet<String> locks = new GridConcurrentHashSet<>();
+
+ /** {@inheritDoc} */
+ @Override public Lock makeLock(String lockName) {
+ return new LockImpl(lockName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void clearLock(String lockName) throws IOException {
+ locks.remove(lockName);
+ }
+
+ /**
+ * {@link Lock} Implementation.
+ */
+ private class LockImpl extends Lock {
+ /** */
+ private final String lockName;
+
+ /**
+ * @param lockName Lock name.
+ */
+ private LockImpl(String lockName) {
+ this.lockName = lockName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean obtain() throws IOException {
+ return locks.add(lockName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void release() throws IOException {
+ locks.remove(lockName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isLocked() throws IOException {
+ return locks.contains(lockName);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneOutputStream.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneOutputStream.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneOutputStream.java
new file mode 100644
index 0000000..ff5abf2
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneOutputStream.java
@@ -0,0 +1,230 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.lucene.store.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+
+import java.io.IOException;
+
+/**
+ * A memory-resident {@link IndexOutput} implementation.
+ */
+public class GridLuceneOutputStream extends IndexOutput {
+ /** Off-heap page size. */
+ static final int BUFFER_SIZE = 32 * 1024;
+
+ /** */
+ private GridLuceneFile file;
+
+ /** */
+ private long currBuf;
+
+ /** */
+ private int currBufIdx;
+
+ /** */
+ private int bufPosition;
+
+ /** */
+ private long bufStart;
+
+ /** */
+ private int bufLength;
+
+ /** */
+ private final GridUnsafeMemory mem;
+
+ /**
+ * Constructor.
+ *
+ * @param f File.
+ */
+ public GridLuceneOutputStream(GridLuceneFile f) {
+ file = f;
+
+ mem = f.getDirectory().memory();
+
+ // make sure that we switch to the
+ // first needed buffer lazily
+ currBufIdx = -1;
+ currBuf = 0;
+ }
+
+ /**
+ * Resets this to an empty file.
+ */
+ public void reset() {
+ currBuf = 0;
+ currBufIdx = -1;
+ bufPosition = 0;
+ bufStart = 0;
+ bufLength = 0;
+
+ file.setLength(0);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close() throws IOException {
+ flush();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void seek(long pos) throws IOException {
+ // set the file length in case we seek back
+ // and flush() has not been called yet
+ setFileLength();
+
+ if (pos < bufStart || pos >= bufStart + bufLength) {
+ currBufIdx = (int)(pos / BUFFER_SIZE);
+
+ switchCurrentBuffer();
+ }
+
+ bufPosition = (int)(pos % BUFFER_SIZE);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long length() {
+ return file.getLength();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeByte(byte b) throws IOException {
+ if (bufPosition == bufLength) {
+ currBufIdx++;
+
+ switchCurrentBuffer();
+ }
+
+ mem.writeByte(currBuf + bufPosition++, b);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeBytes(byte[] b, int offset, int len) throws IOException {
+ assert b != null;
+
+ while (len > 0) {
+ if (bufPosition == bufLength) {
+ currBufIdx++;
+
+ switchCurrentBuffer();
+ }
+
+ int remainInBuf = BUFFER_SIZE - bufPosition;
+ int bytesToCp = len < remainInBuf ? len : remainInBuf;
+
+ mem.writeBytes(currBuf + bufPosition, b, offset, bytesToCp);
+
+ offset += bytesToCp;
+ len -= bytesToCp;
+
+ bufPosition += bytesToCp;
+ }
+ }
+
+ /**
+ * Switch buffer to next.
+ */
+ private void switchCurrentBuffer() {
+ currBuf = currBufIdx == file.numBuffers() ? file.addBuffer() : file.getBuffer(currBufIdx);
+
+ bufPosition = 0;
+ bufStart = (long)BUFFER_SIZE * (long)currBufIdx;
+ bufLength = BUFFER_SIZE;
+ }
+
+ /**
+ * Sets file length.
+ */
+ private void setFileLength() {
+ long pointer = bufStart + bufPosition;
+
+ if (pointer > file.getLength())
+ file.setLength(pointer);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void flush() throws IOException {
+ setFileLength();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getFilePointer() {
+ return currBufIdx < 0 ? 0 : bufStart + bufPosition;
+ }
+
+ /**
+ * Returns byte usage of all buffers.
+ *
+ * @return Bytes used.
+ */
+ public long sizeInBytes() {
+ return (long)file.numBuffers() * (long)BUFFER_SIZE;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void copyBytes(DataInput input, long numBytes) throws IOException {
+ assert numBytes >= 0 : "numBytes=" + numBytes;
+
+ GridLuceneInputStream gridInput = input instanceof GridLuceneInputStream ? (GridLuceneInputStream)input : null;
+
+ while (numBytes > 0) {
+ if (bufPosition == bufLength) {
+ currBufIdx++;
+
+ switchCurrentBuffer();
+ }
+
+ int toCp = BUFFER_SIZE - bufPosition;
+
+ if (numBytes < toCp)
+ toCp = (int)numBytes;
+
+ if (gridInput != null)
+ gridInput.readBytes(currBuf + bufPosition, toCp);
+ else {
+ byte[] buff = new byte[toCp];
+
+ input.readBytes(buff, 0, toCp, false);
+
+ mem.writeBytes(currBuf + bufPosition, buff);
+ }
+
+ numBytes -= toCp;
+ bufPosition += toCp;
+ }
+ }
+
+ /**
+ * For direct usage by {@link GridLuceneInputStream}.
+ *
+ * @param ptr Pointer.
+ * @param len Length.
+ * @throws IOException If failed.
+ */
+ void writeBytes(long ptr, int len) throws IOException {
+ while (len > 0) {
+ if (bufPosition == bufLength) {
+ currBufIdx++;
+ switchCurrentBuffer();
+ }
+
+ int remainInBuf = BUFFER_SIZE - bufPosition;
+ int bytesToCp = len < remainInBuf ? len : remainInBuf;
+
+ mem.copyMemory(ptr, currBuf + bufPosition, bytesToCp);
+
+ ptr += bytesToCp;
+ len -= bytesToCp;
+ bufPosition += bytesToCp;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridSearchRowPointer.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridSearchRowPointer.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridSearchRowPointer.java
new file mode 100644
index 0000000..4f11bfc
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridSearchRowPointer.java
@@ -0,0 +1,20 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.gridgain.grid.util.offheap.unsafe.*;
+import org.h2.result.*;
+
+/**
+ * Search row which supports pointer operations.
+ */
+public interface GridSearchRowPointer extends SearchRow, GridOffHeapSmartPointer {
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/package.html
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/package.html b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/package.html
new file mode 100644
index 0000000..1a7d215
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/package.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ @html.file.header
+ _________ _____ __________________ _____
+ __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+-->
+<html>
+<body>
+ <!-- Package description. -->
+ Contains <b>default</b> H2-based indexing SPI implementation.
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpaceConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpaceConfiguration.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpaceConfiguration.java
deleted file mode 100644
index 1ba7a5d..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpaceConfiguration.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.gridgain.grid.util.typedef.internal.*;
-
-/**
- * Defines per-space configuration properties for {@link GridH2IndexingSpi}.
- */
-public class GridH2IndexingSpaceConfiguration {
- /** */
- private String name;
-
- /** */
- private boolean idxPrimitiveKey;
-
- /** */
- private boolean idxPrimitiveVal;
-
- /** */
- private boolean idxFixedTyping;
-
- /** */
- private boolean escapeAll;
-
- /**
- * Gets space name to which this configuration applies.
- *
- * @return Space name.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Sets space name.
- *
- * @param name Space name.
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * Gets flag indicating whether indexing SPI should index by key in cases
- * where key is primitive type
- *
- * @return {@code True} if primitive keys should be indexed.
- */
- public boolean isIndexPrimitiveKey() {
- return idxPrimitiveKey;
- }
-
- /**
- * Sets flag indicating whether indexing SPI should index by key in cases
- * where key is primitive type.
- *
- * @param idxPrimitiveKey {@code True} if primitive keys should be indexed.
- */
- public void setIndexPrimitiveKey(boolean idxPrimitiveKey) {
- this.idxPrimitiveKey = idxPrimitiveKey;
- }
-
- /**
- * Gets flag indicating whether indexing SPI should index by value in cases
- * where value is primitive type
- *
- * @return {@code True} if primitive values should be indexed.
- */
- public boolean isIndexPrimitiveValue() {
- return idxPrimitiveVal;
- }
-
- /**
- * Sets flag indexing whether indexing SPI should index by value in cases
- * where value is primitive type.
- *
- * @param idxPrimitiveVal {@code True} if primitive values should be indexed.
- */
- public void setIndexPrimitiveValue(boolean idxPrimitiveVal) {
- this.idxPrimitiveVal = idxPrimitiveVal;
- }
-
- /**
- * This flag essentially controls whether all values of the same type have
- * identical key type.
- * <p>
- * If {@code false}, SPI will store all keys in BINARY form to make it possible to store
- * the same value type with different key types. If {@code true}, key type will be converted
- * to respective SQL type if it is possible, hence, improving performance of queries.
- * <p>
- * Setting this value to {@code false} also means that {@code '_key'} column cannot be indexed and
- * cannot participate in query where clauses. The behavior of using '_key' column in where
- * clauses with this flag set to {@code false} is undefined.
- *
- * @return {@code True} if SPI should try to convert values to their respective SQL
- * types for better performance.
- */
- public boolean isIndexFixedTyping() {
- return idxFixedTyping;
- }
-
- /**
- * This flag essentially controls whether key type is going to be identical
- * for all values of the same type.
- * <p>
- * If false, SPI will store all keys in BINARY form to make it possible to store
- * the same value type with different key types. If true, key type will be converted
- * to respective SQL type if it is possible, which may provide significant performance
- * boost.
- *
- * @param idxFixedTyping {@code True} if SPI should try to convert values to their respective SQL
- * types for better performance.
- */
- public void setIndexFixedTyping(boolean idxFixedTyping) {
- this.idxFixedTyping = idxFixedTyping;
- }
-
- /**
- * If {@code true}, then table name and all column names in 'create table' SQL
- * generated by SPI are escaped with double quotes. This flag should be set if table name of
- * column name is H2 reserved word or is not valid H2 identifier (e.g. contains space or hyphen).
- * <p>
- * Note if this flag is set then table and column name in SQL queries also must be escaped with double quotes.
-
- * @return Flag value.
- */
- public boolean isEscapeAll() {
- return escapeAll;
- }
-
- /**
- * If {@code true}, then table name and all column names in 'create table' SQL
- * generated by SPI are escaped with double quotes. This flag should be set if table name of
- * column name is H2 reserved word or is not valid H2 identifier (e.g. contains space or hyphen).
- * <p>
- * Note if this flag is set then table and column name in SQL queries also must be escaped with double quotes.
-
- * @param escapeAll Flag value.
- */
- public void setEscapeAll(boolean escapeAll) {
- this.escapeAll = escapeAll;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(GridH2IndexingSpaceConfiguration.class, this);
- }
-}
[12/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
ignite-qry - merged
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/922a2bab
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/922a2bab
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/922a2bab
Branch: refs/heads/master
Commit: 922a2bab07206f930cab3eb4d930425757bb50b7
Parents: 984373d
Author: S.Vladykin <sv...@gridgain.com>
Authored: Tue Dec 9 19:32:11 2014 +0300
Committer: S.Vladykin <sv...@gridgain.com>
Committed: Tue Dec 9 19:32:11 2014 +0300
----------------------------------------------------------------------
.../MemcacheRestExampleNodeStartup.java | 16 +-
.../jdbc/GridJdbcLocalCachesSelfTest.java | 10 +-
.../configuration/GridQueryConfiguration.java | 194 ++
.../configuration/IgniteConfiguration.java | 28 +-
.../events/IgniteCacheQueryReadEvent.java | 6 +-
.../spi/indexing/GridIndexingQueryFilter.java | 26 +
.../ignite/spi/indexing/GridIndexingSpi.java | 104 +
.../spi/indexing/GridNoopIndexingSpi.java | 58 +
.../ignite/spi/indexing/IndexDescriptor.java | 42 -
.../apache/ignite/spi/indexing/IndexType.java | 24 -
.../ignite/spi/indexing/IndexingEntity.java | 50 -
.../spi/indexing/IndexingEntityAdapter.java | 57 -
.../spi/indexing/IndexingFieldMetadata.java | 46 -
.../spi/indexing/IndexingFieldsResult.java | 35 -
.../indexing/IndexingFieldsResultAdapter.java | 49 -
.../spi/indexing/IndexingKeyValueRow.java | 42 -
.../indexing/IndexingKeyValueRowAdapter.java | 82 -
.../ignite/spi/indexing/IndexingMarshaller.java | 38 -
.../spi/indexing/IndexingQueryFilter.java | 27 -
.../apache/ignite/spi/indexing/IndexingSpi.java | 188 --
.../spi/indexing/IndexingTypeDescriptor.java | 84 -
.../ignite/spi/indexing/NoopIndexingSpi.java | 119 -
.../query/GridCacheQueryConfiguration.java | 117 +
.../grid/cache/query/GridCacheQueryType.java | 5 +-
.../gridgain/grid/kernal/GridComponentType.java | 8 +-
.../org/gridgain/grid/kernal/GridGainEx.java | 5 +-
.../org/gridgain/grid/kernal/GridKernal.java | 2 +
.../gridgain/grid/kernal/GridKernalContext.java | 8 +
.../grid/kernal/GridKernalContextImpl.java | 12 +
.../managers/indexing/GridIndexingManager.java | 1778 +------------
.../GridCacheDistributedFieldsQueryFuture.java | 8 +-
.../query/GridCacheDistributedQueryManager.java | 6 +-
.../query/GridCacheFieldsQueryErrorFuture.java | 6 +-
.../query/GridCacheLocalFieldsQueryFuture.java | 8 +-
.../cache/query/GridCacheLocalQueryManager.java | 6 +-
.../cache/query/GridCacheQueriesEx.java | 7 +
.../cache/query/GridCacheQueriesImpl.java | 21 +-
.../cache/query/GridCacheQueriesProxy.java | 12 +
.../cache/query/GridCacheQueryAdapter.java | 4 +-
.../cache/query/GridCacheQueryManager.java | 396 +--
.../query/GridCacheQueryMetadataAware.java | 4 +-
.../cache/query/GridCacheQueryRequest.java | 4 +-
.../cache/query/GridCacheQueryResponse.java | 135 +-
.../cache/query/GridCacheQueryType.java | 5 +
.../cache/query/GridCacheSqlMetadata.java | 3 +-
.../query/jdbc/GridCacheQueryJdbcTask.java | 6 +-
.../query/GridQueryFieldMetadata.java | 46 +
.../processors/query/GridQueryFieldsResult.java | 34 +
.../query/GridQueryFieldsResultAdapter.java | 49 +
.../query/GridQueryIndexDescriptor.java | 42 +
.../processors/query/GridQueryIndexType.java | 24 +
.../processors/query/GridQueryIndexing.java | 162 ++
.../processors/query/GridQueryProcessor.java | 1672 ++++++++++++
.../query/GridQueryTypeDescriptor.java | 79 +
.../visor/node/VisorSpisConfiguration.java | 2 +-
.../grid/kernal/visor/query/VisorQueryTask.java | 6 +-
.../java/org/gridgain/grid/util/GridUtils.java | 20 +
.../GridCacheTxExceptionAbstractSelfTest.java | 66 +-
.../processors/query/h2/GridH2Indexing.java | 1998 +++++++++++++++
.../query/h2/GridH2ResultSetIterator.java | 122 +
.../query/h2/opt/GridH2AbstractKeyValueRow.java | 447 ++++
.../processors/query/h2/opt/GridH2Cursor.java | 62 +
.../query/h2/opt/GridH2IndexBase.java | 198 ++
.../query/h2/opt/GridH2KeyValueRowOffheap.java | 346 +++
.../query/h2/opt/GridH2KeyValueRowOnheap.java | 46 +
.../processors/query/h2/opt/GridH2Row.java | 40 +
.../query/h2/opt/GridH2RowDescriptor.java | 102 +
.../query/h2/opt/GridH2SpatialIndex.java | 318 +++
.../processors/query/h2/opt/GridH2Table.java | 889 +++++++
.../query/h2/opt/GridH2TreeIndex.java | 469 ++++
.../processors/query/h2/opt/GridH2Utils.java | 125 +
.../query/h2/opt/GridLuceneDirectory.java | 189 ++
.../processors/query/h2/opt/GridLuceneFile.java | 186 ++
.../query/h2/opt/GridLuceneIndex.java | 384 +++
.../query/h2/opt/GridLuceneInputStream.java | 220 ++
.../query/h2/opt/GridLuceneLockFactory.java | 64 +
.../query/h2/opt/GridLuceneOutputStream.java | 230 ++
.../query/h2/opt/GridSearchRowPointer.java | 20 +
.../kernal/processors/query/h2/package.html | 15 +
.../h2/GridH2IndexingSpaceConfiguration.java | 156 --
.../grid/spi/indexing/h2/GridH2IndexingSpi.java | 2398 ------------------
.../spi/indexing/h2/GridH2IndexingSpiMBean.java | 222 --
.../indexing/h2/GridH2ResultSetIterator.java | 122 -
.../h2/opt/GridH2AbstractKeyValueRow.java | 446 ----
.../grid/spi/indexing/h2/opt/GridH2Cursor.java | 62 -
.../spi/indexing/h2/opt/GridH2IndexBase.java | 204 --
.../h2/opt/GridH2KeyValueRowOffheap.java | 346 ---
.../h2/opt/GridH2KeyValueRowOnheap.java | 46 -
.../grid/spi/indexing/h2/opt/GridH2Row.java | 40 -
.../indexing/h2/opt/GridH2RowDescriptor.java | 103 -
.../spi/indexing/h2/opt/GridH2SpatialIndex.java | 318 ---
.../grid/spi/indexing/h2/opt/GridH2Table.java | 893 -------
.../spi/indexing/h2/opt/GridH2TreeIndex.java | 480 ----
.../grid/spi/indexing/h2/opt/GridH2Utils.java | 125 -
.../indexing/h2/opt/GridLuceneDirectory.java | 189 --
.../spi/indexing/h2/opt/GridLuceneFile.java | 186 --
.../spi/indexing/h2/opt/GridLuceneIndex.java | 391 ---
.../indexing/h2/opt/GridLuceneInputStream.java | 220 --
.../indexing/h2/opt/GridLuceneLockFactory.java | 64 -
.../indexing/h2/opt/GridLuceneOutputStream.java | 230 --
.../indexing/h2/opt/GridSearchRowPointer.java | 20 -
.../gridgain/grid/spi/indexing/h2/package.html | 15 -
.../GridCacheAbstractFieldsQuerySelfTest.java | 78 +-
.../cache/GridCacheAbstractQuerySelfTest.java | 27 +-
.../cache/GridCacheCrossCacheQuerySelfTest.java | 9 +-
.../cache/GridCacheOffHeapAndSwapSelfTest.java | 28 +-
.../cache/GridCacheQueryLoadSelfTest.java | 6 +-
.../cache/GridCacheQueryMetricsSelfTest.java | 17 +-
.../GridCacheQueryMultiThreadedSelfTest.java | 57 +-
.../GridCacheQueryUserResourceSelfTest.java | 4 +-
...idCacheReduceQueryMultithreadedSelfTest.java | 13 +-
.../GridCacheSqlQueryMultiThreadedSelfTest.java | 9 +-
.../processors/cache/GridCacheSwapSelfTest.java | 6 +-
.../cache/GridIndexingWithNoopSwapSelfTest.java | 21 +-
...GridCachePartitionedFieldsQuerySelfTest.java | 2 +-
...idCachePartitionedHitsAndMissesSelfTest.java | 20 +-
.../near/GridCacheQueryNodeRestartSelfTest.java | 17 +-
.../GridCacheReplicatedFieldsQuerySelfTest.java | 8 +-
.../GridCacheReplicatedQuerySelfTest.java | 16 +-
.../query/h2/GridH2IndexRebuildTest.java | 241 ++
.../query/h2/GridH2IndexingGeoSelfTest.java | 240 ++
.../query/h2/GridH2IndexingInMemSelfTest.java | 17 +
.../query/h2/GridH2IndexingOffheapSelfTest.java | 36 +
.../h2/GridIndexingSpiAbstractSelfTest.java | 553 ++++
.../query/h2/opt/GridH2TableSelfTest.java | 613 +++++
.../GridIndexingSpiAbstractSelfTest.java | 594 -----
.../spi/indexing/h2/GridH2IndexRebuildTest.java | 236 --
.../h2/GridH2IndexingSpiGeoSelfTest.java | 240 --
.../h2/GridH2IndexingSpiInMemSelfTest.java | 21 -
...GridH2IndexingSpiInMemStartStopSelfTest.java | 21 -
.../h2/GridH2IndexingSpiOffheapSelfTest.java | 40 -
...idH2IndexingSpiOffheapStartStopSelfTest.java | 40 -
.../indexing/h2/opt/GridH2TableSelfTest.java | 613 -----
.../h2/opt/GridLuceneIndexLoadTest.java | 162 --
.../h2indexing/GridH2IndexingSpiLoadTest.java | 288 ---
.../bamboo/GridH2IndexingSpiTestSuite.java | 12 +-
136 files changed, 11394 insertions(+), 12750 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java b/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
index dc5d4a2..616567a 100644
--- a/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
+++ b/examples/src/main/java/org/gridgain/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java
@@ -16,7 +16,7 @@ import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
+import org.gridgain.grid.cache.query.*;
import java.util.*;
@@ -61,13 +61,6 @@ public class MemcacheRestExampleNodeStartup {
cfg.setMarshaller(marsh);
- GridH2IndexingSpi indexSpi = new GridH2IndexingSpi();
-
- indexSpi.setDefaultIndexPrimitiveKey(true);
- indexSpi.setDefaultIndexFixedTyping(false);
-
- cfg.setIndexingSpi(indexSpi);
-
GridCacheConfiguration cacheCfg = new GridCacheConfiguration();
cacheCfg.setAtomicityMode(TRANSACTIONAL);
@@ -75,6 +68,13 @@ public class MemcacheRestExampleNodeStartup {
cacheCfg.setPreloadMode(SYNC);
cacheCfg.setAtomicityMode(TRANSACTIONAL);
+ GridCacheQueryConfiguration qryCfg = new GridCacheQueryConfiguration();
+
+ qryCfg.setIndexPrimitiveKey(true);
+ qryCfg.setIndexFixedTyping(false);
+
+ cacheCfg.setQueryConfiguration(qryCfg);
+
cfg.setCacheConfiguration(cacheCfg);
TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/clients/src/test/java/org/gridgain/jdbc/GridJdbcLocalCachesSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/gridgain/jdbc/GridJdbcLocalCachesSelfTest.java b/modules/clients/src/test/java/org/gridgain/jdbc/GridJdbcLocalCachesSelfTest.java
index 2b217ef..8287bff 100644
--- a/modules/clients/src/test/java/org/gridgain/jdbc/GridJdbcLocalCachesSelfTest.java
+++ b/modules/clients/src/test/java/org/gridgain/jdbc/GridJdbcLocalCachesSelfTest.java
@@ -14,7 +14,7 @@ import org.gridgain.grid.cache.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
+import org.gridgain.grid.cache.query.*;
import org.gridgain.testframework.junits.common.*;
import java.sql.*;
@@ -47,13 +47,13 @@ public class GridJdbcLocalCachesSelfTest extends GridCommonAbstractTest {
cache.setCacheMode(LOCAL);
cache.setWriteSynchronizationMode(FULL_SYNC);
- cfg.setCacheConfiguration(cache);
+ GridCacheQueryConfiguration qryCfg = new GridCacheQueryConfiguration();
- GridH2IndexingSpi idx = new GridH2IndexingSpi();
+ qryCfg.setIndexPrimitiveKey(true);
- idx.setDefaultIndexPrimitiveKey(true);
+ cache.setQueryConfiguration(qryCfg);
- cfg.setIndexingSpi(idx);
+ cfg.setCacheConfiguration(cache);
TcpDiscoverySpi disco = new TcpDiscoverySpi();
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/configuration/GridQueryConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/GridQueryConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/GridQueryConfiguration.java
new file mode 100644
index 0000000..4e3b57a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/GridQueryConfiguration.java
@@ -0,0 +1,194 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.configuration;
+
+import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.jetbrains.annotations.*;
+
+/**
+ * Configuration for embedded indexing facilities.
+ */
+public class GridQueryConfiguration {
+ /** Default query execution time interpreted as long query (3 seconds). */
+ public static final long DFLT_LONG_QRY_EXEC_TIMEOUT = 3000;
+
+ /** Default value for {@link #setUseOptimizedSerializer(boolean)} flag. */
+ public static final boolean DFLT_USE_OPTIMIZED_SERIALIZER = true;
+
+ /** */
+ private Class<?>[] idxCustomFuncClss;
+
+ /** */
+ private String[] searchPath;
+
+ /** */
+ private String initScriptPath;
+
+ /** */
+ private long maxOffHeapMemory = -1;
+
+ /** */
+ private long longQryExecTimeout = DFLT_LONG_QRY_EXEC_TIMEOUT;
+
+ /** */
+ private boolean longQryExplain;
+
+ /** */
+ private boolean useOptimizedSerializer = DFLT_USE_OPTIMIZED_SERIALIZER;
+
+ /**
+ * Sets maximum amount of memory available to off-heap storage. Possible values are
+ * <ul>
+ * <li>{@code -1} - Means that off-heap storage is disabled.</li>
+ * <li>
+ * {@code 0} - GridGain will not limit off-heap storage (it's up to user to properly
+ * add and remove entries from cache to ensure that off-heap storage does not grow
+ * indefinitely.
+ * </li>
+ * <li>Any positive value specifies the limit of off-heap storage in bytes.</li>
+ * </ul>
+ * Default value is {@code -1}, which means that off-heap storage is disabled by default.
+ * <p>
+ * Use off-heap storage to load gigabytes of data in memory without slowing down
+ * Garbage Collection. Essentially in this case you should allocate very small amount
+ * of memory to JVM and GridGain will cache most of the data in off-heap space
+ * without affecting JVM performance at all.
+ *
+ * @param maxOffHeapMemory Maximum memory in bytes available to off-heap memory space.
+ */
+ public void setMaxOffHeapMemory(long maxOffHeapMemory) {
+ this.maxOffHeapMemory = maxOffHeapMemory;
+ }
+
+ /** {@inheritDoc} */
+ public long getMaxOffHeapMemory() {
+ return maxOffHeapMemory;
+ }
+
+ /**
+ * Specifies max allowed size of cache for deserialized offheap rows to avoid deserialization costs for most
+ * frequently used ones. In general performance is better with greater cache size. Must be more than 128 items.
+ *
+ * @param size Cache size in items.
+ */
+ public void setMaxOffheapRowsCacheSize(int size) {
+ A.ensure(size >= 128, "Offheap rows cache size must be not less than 128.");
+
+// rowCache = new CacheLongKeyLIRS<>(size, 1, 128, 256); TODO
+ }
+
+ /**
+ * Sets the optional search path consisting of space names to search SQL schema objects. Useful for cross cache
+ * queries to avoid writing fully qualified table names.
+ *
+ * @param searchPath Search path.
+ */
+ public void setSearchPath(String... searchPath) {
+ this.searchPath = searchPath;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public String[] getSearchPath() {
+ return searchPath;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public String getInitialScriptPath() {
+ return initScriptPath;
+ }
+
+ /**
+ * Sets script path to be ran against H2 database after opening.
+ * The script must be UTF-8 encoded file.
+ *
+ * @param initScriptPath Script path.
+ */
+ public void setInitialScriptPath(String initScriptPath) {
+ this.initScriptPath = initScriptPath;
+ }
+
+ /**
+ * Sets classes with methods annotated by {@link GridCacheQuerySqlFunction}
+ * to be used as user-defined functions from SQL queries.
+ *
+ * @param idxCustomFuncClss List of classes.
+ */
+ public void setIndexCustomFunctionClasses(Class<?>... idxCustomFuncClss) {
+ this.idxCustomFuncClss = idxCustomFuncClss;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public Class<?>[] getIndexCustomFunctionClasses() {
+ return idxCustomFuncClss;
+ }
+
+ /** {@inheritDoc} */
+ public long getLongQueryExecutionTimeout() {
+ return longQryExecTimeout;
+ }
+
+ /**
+ * Set query execution time threshold. If queries exceed this threshold,
+ * then a warning will be printed out. If {@link #setLongQueryExplain(boolean)} is
+ * set to {@code true}, then execution plan will be printed out as well.
+ * <p>
+ * If not provided, default value is defined by {@link #DFLT_LONG_QRY_EXEC_TIMEOUT}.
+ *
+ * @param longQryExecTimeout Long query execution timeout.
+ * @see #setLongQueryExplain(boolean)
+ */
+ public void setLongQueryExecutionTimeout(long longQryExecTimeout) {
+ this.longQryExecTimeout = longQryExecTimeout;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isLongQueryExplain() {
+ return longQryExplain;
+ }
+
+ /**
+ * If {@code true}, SPI will print SQL execution plan for long queries (explain SQL query).
+ * The time threshold of long queries is controlled via {@link #setLongQueryExecutionTimeout(long)}
+ * parameter.
+ * <p>
+ * If not provided, default value is {@code false}.
+ *
+ * @param longQryExplain Flag marking SPI should print SQL execution plan for long queries (explain SQL query).
+ * @see #setLongQueryExecutionTimeout(long)
+ */
+ public void setLongQueryExplain(boolean longQryExplain) {
+ this.longQryExplain = longQryExplain;
+ }
+
+ /**
+ * The flag indicating that serializer for H2 database will be set to GridGain's marshaller.
+ * This setting usually makes sense for offheap indexing only.
+ * <p>
+ * Default is {@link #DFLT_USE_OPTIMIZED_SERIALIZER}.
+ *
+ * @param useOptimizedSerializer Flag value.
+ */
+ public void setUseOptimizedSerializer(boolean useOptimizedSerializer) {
+ this.useOptimizedSerializer = useOptimizedSerializer;
+ }
+
+ /**
+ * The flag indicating that serializer for H2 database will be set to GridGain's marshaller.
+ * This setting usually makes sense for offheap indexing only.
+ * <p>
+ * Default is {@link #DFLT_USE_OPTIMIZED_SERIALIZER}.
+ *
+ * @return Flag value.
+ */
+ public boolean isUseOptimizedSerializer() {
+ return useOptimizedSerializer;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index 92bcdab..b955549 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -370,7 +370,7 @@ public class IgniteConfiguration {
private SwapSpaceSpi swapSpaceSpi;
/** Indexing SPI. */
- private IndexingSpi[] indexingSpi;
+ private GridIndexingSpi indexingSpi;
/** Address resolver. */
private IgniteAddressResolver addrRslvr;
@@ -517,6 +517,9 @@ public class IgniteConfiguration {
/** Warmup closure. Will be invoked before actual grid start. */
private IgniteInClosure<IgniteConfiguration> warmupClos;
+ /** */
+ private GridQueryConfiguration qryCfg;
+
/**
* Creates valid grid configuration with all default values.
*/
@@ -599,6 +602,7 @@ public class IgniteConfiguration {
p2pSvcShutdown = cfg.getPeerClassLoadingExecutorServiceShutdown();
pluginCfgs = cfg.getPluginConfigurations();
portableCfg = cfg.getPortableConfiguration();
+ qryCfg = cfg.getQueryConfiguration();
restAccessibleFolders = cfg.getRestAccessibleFolders();
restEnabled = cfg.isRestEnabled();
restIdleTimeout = cfg.getRestIdleTimeout();
@@ -2147,12 +2151,12 @@ public class IgniteConfiguration {
}
/**
- * Sets fully configured instances of {@link org.apache.ignite.spi.indexing.IndexingSpi}.
+ * Sets fully configured instances of {@link org.apache.ignite.spi.indexing.GridIndexingSpi}.
*
- * @param indexingSpi Fully configured instances of {@link org.apache.ignite.spi.indexing.IndexingSpi}.
+ * @param indexingSpi Fully configured instances of {@link org.apache.ignite.spi.indexing.GridIndexingSpi}.
* @see IgniteConfiguration#getIndexingSpi()
*/
- public void setIndexingSpi(IndexingSpi... indexingSpi) {
+ public void setIndexingSpi(GridIndexingSpi indexingSpi) {
this.indexingSpi = indexingSpi;
}
@@ -2165,7 +2169,7 @@ public class IgniteConfiguration {
*
* @return Indexing SPI implementation or <tt>null</tt> to use default implementation.
*/
- public IndexingSpi[] getIndexingSpi() {
+ public GridIndexingSpi getIndexingSpi() {
return indexingSpi;
}
@@ -3157,6 +3161,20 @@ public class IgniteConfiguration {
this.pluginCfgs = pluginCfgs;
}
+ /**
+ * @return Query configuration.
+ */
+ public GridQueryConfiguration getQueryConfiguration() {
+ return qryCfg;
+ }
+
+ /**
+ * @param qryCfg Query configuration.
+ */
+ public void setQueryConfiguration(GridQueryConfiguration qryCfg) {
+ this.qryCfg = qryCfg;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(IgniteConfiguration.class, this);
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/events/IgniteCacheQueryReadEvent.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/events/IgniteCacheQueryReadEvent.java b/modules/core/src/main/java/org/apache/ignite/events/IgniteCacheQueryReadEvent.java
index e53bb00..cd10d99 100644
--- a/modules/core/src/main/java/org/apache/ignite/events/IgniteCacheQueryReadEvent.java
+++ b/modules/core/src/main/java/org/apache/ignite/events/IgniteCacheQueryReadEvent.java
@@ -101,7 +101,7 @@ public class IgniteCacheQueryReadEvent<K, V> extends IgniteEventAdapter {
/** Result row. */
@GridToStringInclude
- private final List<?> row;
+ private final Object row;
/**
* @param node Node where event was fired.
@@ -133,7 +133,7 @@ public class IgniteCacheQueryReadEvent<K, V> extends IgniteEventAdapter {
@Nullable K key,
@Nullable V val,
@Nullable V oldVal,
- @Nullable List<?> row) {
+ @Nullable Object row) {
super(node, msg, type);
assert qryType != null;
@@ -276,7 +276,7 @@ public class IgniteCacheQueryReadEvent<K, V> extends IgniteEventAdapter {
*
* @return Result row.
*/
- @Nullable public List<?> row() {
+ @Nullable public Object row() {
return row;
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingQueryFilter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingQueryFilter.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingQueryFilter.java
new file mode 100644
index 0000000..f91f414
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingQueryFilter.java
@@ -0,0 +1,26 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.spi.indexing;
+
+import org.apache.ignite.lang.*;
+import org.jetbrains.annotations.*;
+
+/**
+ * Cache entry filter.
+ */
+public interface GridIndexingQueryFilter {
+ /**
+ * Creates optional predicate for space.
+ *
+ * @param spaceName Space name.
+ * @return Predicate or {@code null} if no filtering is needed.
+ */
+ @Nullable public <K, V> IgniteBiPredicate<K, V> forSpace(String spaceName);
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java
new file mode 100644
index 0000000..71cced8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java
@@ -0,0 +1,104 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.spi.indexing;
+
+import org.apache.ignite.spi.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+/**
+ * Indexing SPI allows user to index cache content. Using indexing SPI user can index data in cache and run
+ * Usually cache name will be used as space name, so multiple caches can write to single indexing SPI instance.
+ * <p>
+ * <b>NOTE:</b> this SPI (i.e. methods in this interface) should never be used directly. SPIs provide
+ * internal view on the subsystem and is used internally by GridGain kernal. In rare use cases when
+ * access to a specific implementation of this SPI is required - an instance of this SPI can be obtained
+ * via {@link org.apache.ignite.Ignite#configuration()} method to check its configuration properties or call other non-SPI
+ * methods. Note again that calling methods from this interface on the obtained instance can lead
+ * to undefined behavior and explicitly not supported.
+ *
+ * * Here is a Java example on how to configure grid with {@code GridH2IndexingSpi}.
+ * <pre name="code" class="java">
+ * GridIndexingSpi spi = new MyIndexingSpi();
+ *
+ * GridConfiguration cfg = new GridConfiguration();
+ *
+ * // Overrides default indexing SPI.
+ * cfg.setIndexingSpi(spi);
+ *
+ * // Starts grid.
+ * G.start(cfg);
+ * </pre>
+ * Here is an example of how to configure {@code GridH2IndexingSpi} from Spring XML configuration file.
+ * <pre name="code" class="xml">
+ * <property name="indexingSpi">
+ * <bean class="com.example.MyIndexingSpi">
+ * </bean>
+ * </property>
+ * </pre>
+ * <p>
+ * <img src="http://www.gridgain.com/images/spring-small.png">
+ * <br>
+ * For information about Spring framework visit <a href="http://www.springframework.org/">www.springframework.org</a>
+ */
+public interface GridIndexingSpi extends IgniteSpi {
+ /**
+ * Executes query.
+ *
+ * @param spaceName Space name.
+ * @param params Query parameters.
+ * @param filters System filters.
+ * @return Query result.
+ * @throws IgniteSpiException If failed.
+ */
+ public Iterator<?> query(@Nullable String spaceName, Collection<Object> params,
+ @Nullable GridIndexingQueryFilter filters) throws IgniteSpiException;
+
+ /**
+ * Updates index. Note that key is unique for space, so if space contains multiple indexes
+ * the key should be removed from indexes other than one being updated.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @param val Value.
+ * @param expirationTime Expiration time or 0 if never expires.
+ * @throws IgniteSpiException If failed.
+ */
+ public void store(@Nullable String spaceName, Object key, Object val, long expirationTime) throws IgniteSpiException;
+
+ /**
+ * Removes index entry by key.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @throws IgniteSpiException If failed.
+ */
+ public void remove(@Nullable String spaceName, Object key) throws IgniteSpiException;
+
+ /**
+ * Will be called when entry with given key is swapped.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @throws IgniteSpiException If failed.
+ */
+ public void onSwap(@Nullable String spaceName, Object key) throws IgniteSpiException;
+
+ /**
+ * Will be called when entry with given key is unswapped.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @param val Value.
+ * @throws IgniteSpiException If failed.
+ */
+ public void onUnswap(@Nullable String spaceName, Object key, Object val) throws IgniteSpiException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridNoopIndexingSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridNoopIndexingSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridNoopIndexingSpi.java
new file mode 100644
index 0000000..7883625
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridNoopIndexingSpi.java
@@ -0,0 +1,58 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.apache.ignite.spi.indexing;
+
+import org.apache.ignite.spi.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+/**
+ * Default implementation of {@link GridIndexingSpi} which does not index cache.
+ */
+@IgniteSpiNoop
+public class GridNoopIndexingSpi extends IgniteSpiAdapter implements GridIndexingSpi {
+ /** {@inheritDoc} */
+ @Override public Iterator<?> query(@Nullable String spaceName, Collection<Object> params,
+ @Nullable GridIndexingQueryFilter filters) throws IgniteSpiException {
+ throw new IgniteSpiException("You have to configure custom GridIndexingSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void store(@Nullable String spaceName, Object key, Object val, long expirationTime)
+ throws IgniteSpiException {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(@Nullable String spaceName, Object key) throws IgniteSpiException {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onSwap(@Nullable String spaceName, Object key) throws IgniteSpiException {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onUnswap(@Nullable String spaceName, Object key, Object val) throws IgniteSpiException {
+ assert false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void spiStart(@Nullable String gridName) throws IgniteSpiException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void spiStop() throws IgniteSpiException {
+ // No-op.
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexDescriptor.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexDescriptor.java
deleted file mode 100644
index ada2cc1..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexDescriptor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import java.util.*;
-
-/**
- * Describes an index to be created for a certain type. It contains all necessary
- * information about fields, order, uniqueness, and specified
- * whether this is SQL or Text index.
- * See also {@link IndexingTypeDescriptor#indexes()}.
- */
-public interface IndexDescriptor {
- /**
- * Gets all fields to be indexed.
- *
- * @return Fields to be indexed.
- */
- public Collection<String> fields();
-
- /**
- * Specifies order of the index for each indexed field.
- *
- * @param field Field name.
- * @return {@code True} if given field should be indexed in descending order.
- */
- public boolean descending(String field);
-
- /**
- * Gets index type.
- *
- * @return Type.
- */
- public IndexType type();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexType.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexType.java
deleted file mode 100644
index dcab0a7..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexType.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-/**
- * Index types.
- */
-public enum IndexType {
- /** Sorted SQL index. */
- SORTED,
-
- /** Spatial SQL index. */
- GEO_SPATIAL,
-
- /** Fulltext index. */
- FULLTEXT
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntity.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntity.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntity.java
deleted file mode 100644
index 0208b75..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntity.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.apache.ignite.spi.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-
-/**
- * Wrapper around indexed key or value which also may contain the value in
- * unmarshalled form. It exists to avoid unnecessary unmarshalling whenever
- * it is not needed.
- * See also {@link IndexingSpi#queryFields(String, String, Collection, IndexingQueryFilter[])}.
- */
-public interface IndexingEntity<T> {
- /**
- * Gets indexed value. This method may return {@code null} only
- * if actual value is {@code null}. Otherwise, it will unmarshal
- * the {@link #bytes()} and return the actual value.
- *
- * @return Indexed value.
- * @throws org.apache.ignite.spi.IgniteSpiException If value de-serialization failed.
- */
- @Nullable public T value() throws IgniteSpiException;
-
- /**
- * Optional bytes for marshaled indexed value. Certain SPI implementations
- * may keep objects in unmarshalled form and therefore will not provide
- * marshaled bytes for them.
- *
- * @return Optional marshaled value.
- */
- @Nullable public byte[] bytes();
-
- /**
- * Flag indicating whether this entity contains unmarshalled value.
- *
- * @return {@code True} if entity contains unmarshalled value, {@code false}
- * otherwise.
- */
- public boolean hasValue();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntityAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntityAdapter.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntityAdapter.java
deleted file mode 100644
index d0ca976..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingEntityAdapter.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.grid.util.tostring.*;
-import org.jetbrains.annotations.*;
-
-/**
- * Convenience adapter for {@link IndexingEntity}.
- */
-public class IndexingEntityAdapter<T> implements IndexingEntity<T> {
- /** */
- @GridToStringInclude
- private final T val;
-
- /** */
- @GridToStringExclude
- private final byte[] bytes;
-
- /**
- * @param val Value.
- * @param bytes Value marshalled by {@link org.apache.ignite.marshaller.IgniteMarshaller}.
- */
- public IndexingEntityAdapter(T val, @Nullable byte[] bytes) {
- this.val = val;
- this.bytes = bytes;
- }
-
- /** {@inheritDoc} */
- @Override public T value() {
- return val;
- }
-
- /** {@inheritDoc} */
- @Override public byte[] bytes() {
- return bytes;
- }
-
- /** {@inheritDoc} */
- @Override public boolean hasValue() {
- return val != null || (val == null && bytes == null);
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(IndexingEntityAdapter.class, this,
- "bytesLength", (bytes == null ? 0 : bytes.length));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldMetadata.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldMetadata.java
deleted file mode 100644
index 8b25c84..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldMetadata.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import java.io.*;
-
-/**
- * Query field descriptor. This descriptor is used to provide metadata
- * about fields returned in query result.
- */
-public interface IndexingFieldMetadata extends Externalizable {
- /**
- * Gets schema name.
- *
- * @return Schema name.
- */
- public String schemaName();
-
- /**
- * Gets name of type to which this field belongs.
- *
- * @return Gets type name.
- */
- public String typeName();
-
- /**
- * Gets field name.
- *
- * @return Field name.
- */
- public String fieldName();
-
- /**
- * Gets field type name.
- *
- * @return Field type name.
- */
- public String fieldTypeName();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResult.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResult.java
deleted file mode 100644
index 62e6ce1..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResult.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.apache.ignite.spi.*;
-
-import java.util.*;
-
-/**
- * Field query result. It is composed of
- * fields metadata and iterator over queried fields.
- * See also {@link IndexingSpi#queryFields(String, String, Collection, IndexingQueryFilter)}.
- */
-public interface IndexingFieldsResult {
- /**
- * Gets metadata for queried fields.
- *
- * @return Meta data for queried fields.
- */
- List<IndexingFieldMetadata> metaData();
-
- /**
- * Gets iterator over queried fields.
- *
- * @return Iterator over queried fields.
- */
- IgniteSpiCloseableIterator<List<IndexingEntity<?>>> iterator();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResultAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResultAdapter.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResultAdapter.java
deleted file mode 100644
index c583b76..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingFieldsResultAdapter.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.apache.ignite.spi.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-
-/**
- * Convenience adapter for {@link IndexingFieldsResult}.
- */
-public class IndexingFieldsResultAdapter implements IndexingFieldsResult {
- /** Meta data. */
- private final List<IndexingFieldMetadata> metaData;
-
- /** Result iterator. */
- private final IgniteSpiCloseableIterator<List<IndexingEntity<?>>> it;
-
- /**
- * Creates query field result composed of field metadata and iterator
- * over queried fields.
- *
- * @param metaData Meta data.
- * @param it Result iterator.
- */
- public IndexingFieldsResultAdapter(@Nullable List<IndexingFieldMetadata> metaData,
- IgniteSpiCloseableIterator<List<IndexingEntity<?>>> it) {
- this.metaData = metaData != null ? Collections.unmodifiableList(metaData) : null;
- this.it = it;
- }
-
- /** {@inheritDoc} */
- @Override public List<IndexingFieldMetadata> metaData() {
- return metaData;
- }
-
- /** {@inheritDoc} */
- @Override public IgniteSpiCloseableIterator<List<IndexingEntity<?>>> iterator() {
- return it;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRow.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRow.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRow.java
deleted file mode 100644
index 7b075ed..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRow.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import java.util.*;
-
-/**
- * This class represents a single row returned by key-value query. For example, it is returned
- * by query such as {@link IndexingSpi#query(String, String, Collection, IndexingTypeDescriptor, IndexingQueryFilter[])}
- * method. Key-value queries are different from fields query in a way that they
- * return the whole cached value, not its individual fields.
- * See also {@link IndexingSpi#query(String, String, Collection, IndexingTypeDescriptor, IndexingQueryFilter[])}.
- */
-public interface IndexingKeyValueRow<K, V> {
- /**
- * Gets cache key.
- *
- * @return Cache key.
- */
- public IndexingEntity<K> key();
-
- /**
- * Gets cache value.
- *
- * @return Cache value.
- */
- public IndexingEntity<V> value();
-
- /**
- * Gets version of cache value.
- *
- * @return Version of cache value.
- */
- public byte[] version();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRowAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRowAdapter.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRowAdapter.java
deleted file mode 100644
index f703c51..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingKeyValueRowAdapter.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
-* __ ____/___________(_)______ /__ ____/______ ____(_)_______
-* _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
-* / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
-* \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
-*/
-
-package org.apache.ignite.spi.indexing;
-
-import org.gridgain.grid.kernal.processors.cache.query.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.grid.util.tostring.*;
-import org.jetbrains.annotations.*;
-
-/**
- * Convenience adapter for {@link IndexingKeyValueRow}.
- */
-public class IndexingKeyValueRowAdapter<K, V> implements IndexingKeyValueRow<K, V> {
- /** Key. */
- @GridToStringInclude
- private IndexingEntity<K> key;
-
- /** Value. */
- @GridToStringInclude
- private IndexingEntity<V> val;
-
- /** Version. */
- @GridToStringInclude
- private byte[] ver;
-
- /**
- * Constructor.
- *
- * @param key Key.
- * @param val Value.
- */
- public IndexingKeyValueRowAdapter(K key, V val) {
- assert key != null;
- assert val != null;
-
- this.key = new IndexingEntityAdapter<>(key, null);
- this.val = new IndexingEntityAdapter<>(val, null);
- }
-
- /**
- * Constructs query index row.
- *
- * @param key Key.
- * @param val Value.
- * @param ver Version. It is {@code null} in case of {@link GridCacheQueryType#SCAN} query.
- */
- public IndexingKeyValueRowAdapter(IndexingEntity<K> key, @Nullable IndexingEntity<V> val,
- @Nullable byte[] ver) {
- assert key != null;
-
- this.key = key;
- this.val = val;
- this.ver = ver;
- }
-
- /** {@inheritDoc} */
- @Override public IndexingEntity<K> key() {
- return key;
- }
-
- /** {@inheritDoc} */
- @Override public IndexingEntity<V> value() {
- return val;
- }
-
- /** {@inheritDoc} */
- @Override public byte[] version() {
- return ver;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(IndexingKeyValueRowAdapter.class, this);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingMarshaller.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingMarshaller.java
deleted file mode 100644
index e04c6a1..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingMarshaller.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.apache.ignite.spi.*;
-
-/**
- * Marshaller to be used in indexing SPI. This marshaller automatically
- * takes care of class loading of unmarshalled classes.
- * See also {@link IndexingSpi#registerMarshaller(IndexingMarshaller)}.
- */
-public interface IndexingMarshaller {
- /**
- * Unmarshalls bytes to object.
- *
- * @param bytes Bytes.
- * @param <T> Value type.
- * @return Value.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <T> IndexingEntity<T> unmarshal(byte[] bytes) throws IgniteSpiException;
-
- /**
- * Marshals object to bytes.
- *
- * @param entity Entity.
- * @return Bytes.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public byte[] marshal(IndexingEntity<?> entity) throws IgniteSpiException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingQueryFilter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingQueryFilter.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingQueryFilter.java
deleted file mode 100644
index bbdcdf6..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingQueryFilter.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.apache.ignite.lang.*;
-import org.gridgain.grid.*;
-import org.jetbrains.annotations.*;
-
-/**
- * Space name and key filter.
- */
-public interface IndexingQueryFilter {
- /**
- * Creates optional predicate for space.
- *
- * @param spaceName Space name.
- * @return Predicate or {@code null} if no filtering is needed.
- */
- @Nullable public <K, V> IgniteBiPredicate<K, V> forSpace(String spaceName) throws GridException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingSpi.java
deleted file mode 100644
index 74de3dd..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingSpi.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.apache.ignite.spi.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-
-/**
- * Indexing SPI allows user to index cache content. Using indexing SPI user can index data in cache and run SQL,
- * TEXT or individual field queries against these indexes. Usually indexing SPI is used by caches by name
- * (see {@link GridCacheConfiguration#getIndexingSpiName()}). Logically storage is organized into separate spaces.
- * Usually cache name will be used as space name, so multiple caches can write to single indexing SPI instance.
- * <p>
- * Functionality of this SPI is exposed to {@link GridCacheQueries} interface:
- * <ul>
- * <li>{@link GridCacheQueries#createSqlQuery(Class, String)}</li>
- * <li>{@link GridCacheQueries#createSqlFieldsQuery(String)}</li>
- * <li>{@link GridCacheQueries#createFullTextQuery(Class, String)}</li>
- * </ul>
- * <p>
- * The default indexing SPI implementation is
- * {@gglink org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi} which uses H2 database engine
- * for data indexing and querying. User can implement his own indexing SPI and use his own data structures
- * and query language instead of SQL. SPI can be configured for grid using {@link org.apache.ignite.configuration.IgniteConfiguration#getIndexingSpi()}.
- * <p>
- * GridGain comes with following built-in indexing SPI implementations:
- * <ul>
- * <li>{@gglink org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi}</li>
- * </ul>
- * <p>
- * <b>NOTE:</b> this SPI (i.e. methods in this interface) should never be used directly. SPIs provide
- * internal view on the subsystem and is used internally by GridGain kernal. In rare use cases when
- * access to a specific implementation of this SPI is required - an instance of this SPI can be obtained
- * via {@link org.apache.ignite.Ignite#configuration()} method to check its configuration properties or call other non-SPI
- * methods. Note again that calling methods from this interface on the obtained instance can lead
- * to undefined behavior and explicitly not supported.
- */
-public interface IndexingSpi extends IgniteSpi {
- /**
- * Queries individual fields (generally used by JDBC drivers).
- *
- * @param spaceName Space name.
- * @param qry Query.
- * @param params Query parameters.
- * @param filters Space name and key filters.
- * @return Query result.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K, V> IndexingFieldsResult queryFields(@Nullable String spaceName, String qry,
- Collection<Object> params, IndexingQueryFilter filters) throws IgniteSpiException;
-
- /**
- * Executes regular query.
- *
- * @param spaceName Space name.
- * @param qry Query.
- * @param params Query parameters.
- * @param type Query return type.
- * @param filters Space name and key filters.
- * @return Queried rows.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> query(@Nullable String spaceName, String qry,
- Collection<Object> params, IndexingTypeDescriptor type, IndexingQueryFilter filters)
- throws IgniteSpiException;
-
- /**
- * Executes text query.
- *
- * @param spaceName Space name.
- * @param qry Text query.
- * @param type Query return type.
- * @param filters Space name and key filter.
- * @return Queried rows.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> queryText(@Nullable String spaceName, String qry,
- IndexingTypeDescriptor type, IndexingQueryFilter filters) throws IgniteSpiException;
-
- /**
- * Gets size of index for given type or -1 if it is a unknown type.
- *
- * @param spaceName Space name.
- * @param desc Type descriptor.
- * @return Objects number.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public long size(@Nullable String spaceName, IndexingTypeDescriptor desc) throws IgniteSpiException;
-
- /**
- * Registers type if it was not known before or updates it otherwise.
- *
- * @param spaceName Space name.
- * @param desc Type descriptor.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- * @return {@code True} if type was registered, {@code false} if for some reason it was rejected.
- */
- public boolean registerType(@Nullable String spaceName, IndexingTypeDescriptor desc) throws IgniteSpiException;
-
- /**
- * Unregisters type and removes all corresponding data.
- *
- * @param spaceName Space name.
- * @param type Type descriptor.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public void unregisterType(@Nullable String spaceName, IndexingTypeDescriptor type) throws IgniteSpiException;
-
- /**
- * Updates index. Note that key is unique for space, so if space contains multiple indexes
- * the key should be removed from indexes other than one being updated.
- *
- * @param spaceName Space name.
- * @param type Value type.
- * @param key Key.
- * @param val Value.
- * @param ver Version.
- * @param expirationTime Expiration time or 0 if never expires.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K, V> void store(@Nullable String spaceName, IndexingTypeDescriptor type, IndexingEntity<K> key,
- IndexingEntity<V> val, byte[] ver, long expirationTime) throws IgniteSpiException;
-
- /**
- * Removes index entry by key.
- *
- * @param spaceName Space name.
- * @param key Key.
- * @return {@code True} if removed by this operation, {@code false} otherwise.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K> boolean remove(@Nullable String spaceName, IndexingEntity<K> key) throws IgniteSpiException;
-
- /**
- * Will be called when entry with given key is swapped.
- *
- * @param spaceName Space name.
- * @param swapSpaceName Swap space name.
- * @param key Key.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K> void onSwap(@Nullable String spaceName, String swapSpaceName, K key) throws IgniteSpiException;
-
- /**
- * Will be called when entry with given key is unswapped.
- *
- * @param spaceName Space name.
- * @param key Key.
- * @param val Value.
- * @param valBytes Value bytes.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <K, V> void onUnswap(@Nullable String spaceName, K key, V val, byte[] valBytes) throws IgniteSpiException;
-
- /**
- * Marshaller to be used by SPI.
- *
- * @param marshaller Marshaller.
- */
- public void registerMarshaller(IndexingMarshaller marshaller);
-
- /**
- * Registers space in this SPI.
- *
- * @param spaceName Space name.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public void registerSpace(String spaceName) throws IgniteSpiException;
-
- /**
- * Rebuilds all indexes of given type.
- *
- * @param spaceName Space name.
- * @param type Type descriptor.
- */
- public void rebuildIndexes(@Nullable String spaceName, IndexingTypeDescriptor type);
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingTypeDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingTypeDescriptor.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingTypeDescriptor.java
deleted file mode 100644
index 3f96b1c..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/IndexingTypeDescriptor.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-
-import org.apache.ignite.spi.*;
-
-import java.util.*;
-
-/**
- * Value descriptor which allows to extract fields from value object of given type.
- * See also {@link IndexingSpi#registerType(String, IndexingTypeDescriptor)}.
- */
-public interface IndexingTypeDescriptor {
- /**
- * Gets type name which uniquely identifies this type.
- *
- * @return Type name which uniquely identifies this type.
- */
- public String name();
-
- /**
- * Gets mapping from values field name to its type.
- *
- * @return Fields that can be indexed, participate in queries and can be queried using
- * {@link IndexingSpi#queryFields(String, String, Collection, IndexingQueryFilter[])}
- * method.
- */
- public Map<String, Class<?>> valueFields();
-
- /**
- * Gets mapping from keys field name to its type.
- *
- * @return Fields that can be indexed, participate in queries and can be queried using
- * {@link IndexingSpi#queryFields(String, String, Collection, IndexingQueryFilter[])}
- * method.
- */
- public Map<String, Class<?>> keyFields();
-
- /**
- * Gets field value for given object.
- *
- * @param obj Object to get field value from.
- * @param field Field name.
- * @return Value for given field.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public <T> T value(Object obj, String field) throws IgniteSpiException;
-
- /**
- * Gets indexes for this type.
- *
- * @return Indexes for this type.
- */
- public Map<String, IndexDescriptor> indexes();
-
- /**
- * Gets value class.
- *
- * @return Value class.
- */
- public Class<?> valueClass();
-
- /**
- * Gets key class.
- *
- * @return Key class.
- */
- public Class<?> keyClass();
-
- /**
- * Returns {@code true} if string representation of value should be indexed as text.
- *
- * @return If string representation of value should be full-text indexed.
- */
- public boolean valueTextIndex();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/apache/ignite/spi/indexing/NoopIndexingSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/NoopIndexingSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/NoopIndexingSpi.java
deleted file mode 100644
index 9fba743..0000000
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/NoopIndexingSpi.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.apache.ignite.spi.indexing;
-
-import org.apache.ignite.*;
-import org.apache.ignite.resources.*;
-import org.apache.ignite.spi.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-
-/**
- * No-op implementation of {@link IndexingSpi}, throws exception on query attempt.
- */
-@IgniteSpiNoop
-public class NoopIndexingSpi extends IgniteSpiAdapter implements IndexingSpi {
- /** */
- @IgniteLoggerResource
- private IgniteLogger log;
-
- /** {@inheritDoc} */
- @Override public <K, V> IndexingFieldsResult queryFields(@Nullable String spaceName, String qry,
- Collection<Object> params, IndexingQueryFilter filters) throws IgniteSpiException {
- throw spiException();
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> query(@Nullable String spaceName,
- String qry, Collection<Object> params, IndexingTypeDescriptor type,
- IndexingQueryFilter filters) throws IgniteSpiException {
- throw spiException();
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> queryText(@Nullable
- String spaceName, String qry, IndexingTypeDescriptor type, IndexingQueryFilter filters)
- throws IgniteSpiException {
- throw spiException();
- }
-
- /** {@inheritDoc} */
- @Override public long size(@Nullable String spaceName, IndexingTypeDescriptor desc) throws IgniteSpiException {
- throw spiException();
- }
-
- /** {@inheritDoc} */
- @Override public boolean registerType(@Nullable String spaceName, IndexingTypeDescriptor desc)
- throws IgniteSpiException {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public void unregisterType(@Nullable String spaceName, IndexingTypeDescriptor type)
- throws IgniteSpiException {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> void store(@Nullable String spaceName, IndexingTypeDescriptor type,
- IndexingEntity<K> key, IndexingEntity<V> val, byte[] ver, long expirationTime) throws IgniteSpiException {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public <K> boolean remove(@Nullable String spaceName, IndexingEntity<K> key) throws IgniteSpiException {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public <K> void onSwap(@Nullable String spaceName, String swapSpaceName, K key) throws IgniteSpiException {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> void onUnswap(@Nullable String spaceName, K key, V val, byte[] valBytes)
- throws IgniteSpiException {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void registerMarshaller(IndexingMarshaller marshaller) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void registerSpace(String spaceName) throws IgniteSpiException {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void rebuildIndexes(@Nullable String spaceName, IndexingTypeDescriptor type) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void spiStart(@Nullable String gridName) throws IgniteSpiException {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void spiStop() throws IgniteSpiException {
- // No-op.
- }
-
- /**
- * @return No-op SPI usage exception.
- */
- private IgniteSpiException spiException() {
- return new IgniteSpiException("Current grid configuration does not support queries " +
- "(please configure GridH2IndexingSpi).");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryConfiguration.java b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryConfiguration.java
index 625a1ad..ce53d18 100644
--- a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryConfiguration.java
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryConfiguration.java
@@ -25,6 +25,18 @@ public class GridCacheQueryConfiguration implements Serializable {
/** Query type resolver. */
private GridCacheQueryTypeResolver typeRslvr;
+ /** */
+ private boolean idxPrimitiveKey;
+
+ /** */
+ private boolean idxPrimitiveVal;
+
+ /** */
+ private boolean idxFixedTyping;
+
+ /** */
+ private boolean escapeAll;
+
/**
* Default constructor.
*/
@@ -38,6 +50,10 @@ public class GridCacheQueryConfiguration implements Serializable {
public GridCacheQueryConfiguration(GridCacheQueryConfiguration cfg) {
typeMeta = cfg.getTypeMetadata();
typeRslvr = cfg.getTypeResolver();
+ idxPrimitiveKey = cfg.isIndexPrimitiveKey();
+ idxPrimitiveVal = cfg.isIndexPrimitiveValue();
+ idxFixedTyping = cfg.isIndexFixedTyping();
+ escapeAll = cfg.isEscapeAll();
}
/**
@@ -75,4 +91,105 @@ public class GridCacheQueryConfiguration implements Serializable {
public void setTypeResolver(GridCacheQueryTypeResolver typeRslvr) {
this.typeRslvr = typeRslvr;
}
+
+ /**
+ * Gets flag indicating whether SQL engine should index by key in cases
+ * where key is primitive type
+ *
+ * @return {@code True} if primitive keys should be indexed.
+ */
+ public boolean isIndexPrimitiveKey() {
+ return idxPrimitiveKey;
+ }
+
+ /**
+ * Sets flag indicating whether SQL engine should index by key in cases
+ * where key is primitive type.
+ *
+ * @param idxPrimitiveKey {@code True} if primitive keys should be indexed.
+ */
+ public void setIndexPrimitiveKey(boolean idxPrimitiveKey) {
+ this.idxPrimitiveKey = idxPrimitiveKey;
+ }
+
+ /**
+ * Gets flag indicating whether SQL engine should index by value in cases
+ * where value is primitive type
+ *
+ * @return {@code True} if primitive values should be indexed.
+ */
+ public boolean isIndexPrimitiveValue() {
+ return idxPrimitiveVal;
+ }
+
+ /**
+ * Sets flag indexing whether SQL engine should index by value in cases
+ * where value is primitive type.
+ *
+ * @param idxPrimitiveVal {@code True} if primitive values should be indexed.
+ */
+ public void setIndexPrimitiveValue(boolean idxPrimitiveVal) {
+ this.idxPrimitiveVal = idxPrimitiveVal;
+ }
+
+ /**
+ * This flag essentially controls whether all values of the same type have
+ * identical key type.
+ * <p>
+ * If {@code false}, SQL engine will store all keys in BINARY form to make it possible to store
+ * the same value type with different key types. If {@code true}, key type will be converted
+ * to respective SQL type if it is possible, hence, improving performance of queries.
+ * <p>
+ * Setting this value to {@code false} also means that {@code '_key'} column cannot be indexed and
+ * cannot participate in query where clauses. The behavior of using '_key' column in where
+ * clauses with this flag set to {@code false} is undefined.
+ *
+ * @return {@code True} if SQL engine should try to convert values to their respective SQL
+ * types for better performance.
+ */
+ public boolean isIndexFixedTyping() {
+ return idxFixedTyping;
+ }
+
+ /**
+ * This flag essentially controls whether key type is going to be identical
+ * for all values of the same type.
+ * <p>
+ * If false, SQL engine will store all keys in BINARY form to make it possible to store
+ * the same value type with different key types. If true, key type will be converted
+ * to respective SQL type if it is possible, which may provide significant performance
+ * boost.
+ *
+ * @param idxFixedTyping {@code True} if SQL engine should try to convert values to their respective SQL
+ * types for better performance.
+ */
+ public void setIndexFixedTyping(boolean idxFixedTyping) {
+ this.idxFixedTyping = idxFixedTyping;
+ }
+
+ /**
+ * If {@code true}, then table name and all column names in 'create table' SQL
+ * generated for SQL engine are escaped with double quotes. This flag should be set if table name of
+ * column name is H2 reserved word or is not valid H2 identifier (e.g. contains space or hyphen).
+ * <p>
+ * Note if this flag is set then table and column name in SQL queries also must be escaped with double quotes.
+
+ * @return Flag value.
+ */
+ public boolean isEscapeAll() {
+ return escapeAll;
+ }
+
+ /**
+ * If {@code true}, then table name and all column names in 'create table' SQL
+ * generated for SQL engine are escaped with double quotes. This flag should be set if table name of
+ * column name is H2 reserved word or is not valid H2 identifier (e.g. contains space or hyphen).
+ * <p>
+ * Note if this flag is set then table and column name in SQL queries also must be escaped with double quotes.
+
+ * @param escapeAll Flag value.
+ */
+ public void setEscapeAll(boolean escapeAll) {
+ this.escapeAll = escapeAll;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryType.java b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryType.java
index 5d45d87..85d348a 100644
--- a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryType.java
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQueryType.java
@@ -32,5 +32,8 @@ public enum GridCacheQueryType {
SCAN,
/** Continuous query. */
- CONTINUOUS
+ CONTINUOUS,
+
+ /** SPI query. */
+ SPI
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/GridComponentType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/GridComponentType.java b/modules/core/src/main/java/org/gridgain/grid/kernal/GridComponentType.java
index 59ce18f..032c489 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/GridComponentType.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/GridComponentType.java
@@ -46,10 +46,10 @@ public enum GridComponentType {
"gridgain-spring"
),
- /** H2 indexing SPI. */
- H2_INDEXING(
- "org.apache.ignite.spi.indexing.NoopIndexingSpi",
- "org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi",
+ /** Indexing. */
+ INDEXING(
+ null,
+ "org.gridgain.grid.kernal.processors.query.h2.GridH2Indexing",
"gridgain-indexing"
),
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/GridGainEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/GridGainEx.java b/modules/core/src/main/java/org/gridgain/grid/kernal/GridGainEx.java
index 9d72e65..1b622c5 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/GridGainEx.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/GridGainEx.java
@@ -1382,6 +1382,7 @@ public class GridGainEx {
myCfg.setDotNetConfiguration(cfg.getDotNetConfiguration());
myCfg.setPluginConfigurations(cfg.getPluginConfigurations());
myCfg.setTransactionsConfiguration(new GridTransactionsConfiguration(cfg.getTransactionsConfiguration()));
+ myCfg.setQueryConfiguration(cfg.getQueryConfiguration());
ClientConnectionConfiguration clientCfg = cfg.getClientConnectionConfiguration();
@@ -1474,7 +1475,7 @@ public class GridGainEx {
FailoverSpi[] failSpi = cfg.getFailoverSpi();
LoadBalancingSpi[] loadBalancingSpi = cfg.getLoadBalancingSpi();
SwapSpaceSpi swapspaceSpi = cfg.getSwapSpaceSpi();
- IndexingSpi[] indexingSpi = cfg.getIndexingSpi();
+ GridIndexingSpi indexingSpi = cfg.getIndexingSpi();
execSvc = cfg.getExecutorService();
sysExecSvc = cfg.getSystemExecutorService();
@@ -1722,7 +1723,7 @@ public class GridGainEx {
}
if (indexingSpi == null)
- indexingSpi = new IndexingSpi[] {(IndexingSpi)H2_INDEXING.createOptional()};
+ indexingSpi = new GridNoopIndexingSpi();
myCfg.setCommunicationSpi(commSpi);
myCfg.setDiscoverySpi(discoSpi);
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernal.java b/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernal.java
index d913605..2ec852b 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernal.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernal.java
@@ -54,6 +54,7 @@ import org.gridgain.grid.kernal.processors.offheap.*;
import org.gridgain.grid.kernal.processors.plugin.*;
import org.gridgain.grid.kernal.processors.port.*;
import org.gridgain.grid.kernal.processors.portable.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.kernal.processors.resource.*;
import org.gridgain.grid.kernal.processors.rest.*;
import org.gridgain.grid.kernal.processors.segmentation.*;
@@ -724,6 +725,7 @@ public class GridKernal extends ClusterGroupAdapter implements GridEx, IgniteMBe
startProcessor(ctx, createComponent(GridLicenseProcessor.class, ctx), attrs);
startProcessor(ctx, new GridAffinityProcessor(ctx), attrs);
startProcessor(ctx, createComponent(GridSegmentationProcessor.class, ctx), attrs);
+ startProcessor(ctx, new GridQueryProcessor(ctx), attrs);
startProcessor(ctx, new GridCacheProcessor(ctx), attrs);
startProcessor(ctx, new GridTaskSessionProcessor(ctx), attrs);
startProcessor(ctx, new GridJobProcessor(ctx), attrs);
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContext.java b/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContext.java
index 0cf12e3..7b161a4 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContext.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContext.java
@@ -43,6 +43,7 @@ import org.gridgain.grid.kernal.processors.offheap.*;
import org.gridgain.grid.kernal.processors.plugin.*;
import org.gridgain.grid.kernal.processors.port.*;
import org.gridgain.grid.kernal.processors.portable.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.kernal.processors.resource.*;
import org.gridgain.grid.kernal.processors.rest.*;
import org.gridgain.grid.kernal.processors.schedule.*;
@@ -329,6 +330,13 @@ public interface GridKernalContext extends GridMetadataAware, Iterable<GridCompo
public GridInteropProcessor interop();
/**
+ * Gets query processor.
+ *
+ * @return Query processor.
+ */
+ public GridQueryProcessor query();
+
+ /**
* @return Plugin processor.
*/
public IgnitePluginProcessor plugins();
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContextImpl.java b/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContextImpl.java
index 4af386f..41e435e 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernalContextImpl.java
@@ -45,6 +45,7 @@ import org.gridgain.grid.kernal.processors.offheap.*;
import org.gridgain.grid.kernal.processors.plugin.*;
import org.gridgain.grid.kernal.processors.port.*;
import org.gridgain.grid.kernal.processors.portable.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.kernal.processors.resource.*;
import org.gridgain.grid.kernal.processors.rest.*;
import org.gridgain.grid.kernal.processors.schedule.*;
@@ -141,6 +142,10 @@ public class GridKernalContextImpl extends GridMetadataAwareAdapter implements G
/** */
@GridToStringInclude
+ private GridQueryProcessor qryProc;
+
+ /** */
+ @GridToStringInclude
private GridTaskProcessor taskProc;
/** */
@@ -438,6 +443,8 @@ public class GridKernalContextImpl extends GridMetadataAwareAdapter implements G
interopProc = (GridInteropProcessor)comp;
else if (comp instanceof IgnitePluginProcessor)
pluginProc = (IgnitePluginProcessor)comp;
+ else if (comp instanceof GridQueryProcessor)
+ qryProc = (GridQueryProcessor)comp;
else
assert (comp instanceof GridPluginComponent) : "Unknown manager class: " + comp.getClass();
@@ -690,6 +697,11 @@ public class GridKernalContextImpl extends GridMetadataAwareAdapter implements G
}
/** {@inheritDoc} */
+ @Override public GridQueryProcessor query() {
+ return qryProc;
+ }
+
+ /** {@inheritDoc} */
@Override public IgniteLogger log() {
return config().getGridLogger();
}
[02/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java
index b2355ee..430c4cb 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java
@@ -14,7 +14,6 @@ import org.apache.ignite.lang.*;
import org.apache.ignite.marshaller.optimized.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
-import org.gridgain.grid.spi.indexing.h2.*;
import org.gridgain.grid.util.typedef.*;
import java.util.*;
@@ -48,12 +47,6 @@ public class GridCacheReduceQueryMultithreadedSelfTest extends GridCacheAbstract
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
IgniteConfiguration c = super.getConfiguration(gridName);
- GridH2IndexingSpi indexing = new GridH2IndexingSpi();
-
- indexing.setDefaultIndexPrimitiveKey(true);
-
- c.setIndexingSpi(indexing);
-
c.setMarshaller(new IgniteOptimizedMarshaller(false));
return c;
@@ -67,6 +60,12 @@ public class GridCacheReduceQueryMultithreadedSelfTest extends GridCacheAbstract
cfg.setBackups(1);
cfg.setWriteSynchronizationMode(FULL_SYNC);
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
+
+ qcfg.setIndexPrimitiveKey(true);
+
+ cfg.setQueryConfiguration(qcfg);
+
return cfg;
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSqlQueryMultiThreadedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSqlQueryMultiThreadedSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSqlQueryMultiThreadedSelfTest.java
index 11ddf84..3a03ea8 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSqlQueryMultiThreadedSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSqlQueryMultiThreadedSelfTest.java
@@ -10,12 +10,11 @@
package org.gridgain.grid.kernal.processors.cache;
import org.apache.ignite.configuration.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
import org.gridgain.testframework.*;
import org.gridgain.testframework.junits.common.*;
@@ -44,10 +43,6 @@ public class GridCacheSqlQueryMultiThreadedSelfTest extends GridCommonAbstractTe
c.setDiscoverySpi(disco);
- GridH2IndexingSpi indexing = new GridH2IndexingSpi();
-
- c.setIndexingSpi(indexing);
-
GridCacheConfiguration ccfg = new GridCacheConfiguration();
ccfg.setCacheMode(PARTITIONED);
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapSelfTest.java
index 1df68e9..c8adf83 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapSelfTest.java
@@ -14,13 +14,13 @@ import org.apache.ignite.configuration.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
import org.apache.ignite.marshaller.optimized.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
import org.apache.ignite.spi.swapspace.*;
import org.apache.ignite.spi.swapspace.noop.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.testframework.junits.common.*;
@@ -29,11 +29,11 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import static java.util.concurrent.TimeUnit.*;
+import static org.apache.ignite.events.IgniteEventType.*;
import static org.apache.ignite.configuration.IgniteDeploymentMode.*;
import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCachePeekMode.*;
import static org.gridgain.grid.cache.GridCacheWriteSynchronizationMode.*;
-import static org.apache.ignite.events.IgniteEventType.*;
/**
* Test for cache swap.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridIndexingWithNoopSwapSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridIndexingWithNoopSwapSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridIndexingWithNoopSwapSelfTest.java
index 9cdb1c7..ee404cf 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridIndexingWithNoopSwapSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/GridIndexingWithNoopSwapSelfTest.java
@@ -11,15 +11,14 @@ package org.gridgain.grid.kernal.processors.cache;
import org.apache.ignite.*;
import org.apache.ignite.configuration.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.eviction.fifo.*;
-import org.gridgain.grid.cache.query.*;
-import org.gridgain.grid.kernal.processors.cache.GridCacheAbstractQuerySelfTest.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
import org.apache.ignite.spi.swapspace.noop.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.eviction.fifo.*;
+import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.kernal.processors.cache.GridCacheAbstractQuerySelfTest.*;
import org.gridgain.testframework.junits.common.*;
import java.util.*;
@@ -48,12 +47,6 @@ public class GridIndexingWithNoopSwapSelfTest extends GridCommonAbstractTest {
c.setDiscoverySpi(disco);
- GridH2IndexingSpi indexing = new GridH2IndexingSpi();
-
- indexing.setDefaultIndexPrimitiveKey(true);
-
- c.setIndexingSpi(indexing);
-
c.setSwapSpaceSpi(new NoopSwapSpaceSpi());
GridCacheConfiguration cc = defaultCacheConfiguration();
@@ -68,6 +61,12 @@ public class GridIndexingWithNoopSwapSelfTest extends GridCommonAbstractTest {
cc.setBackups(1);
cc.setAtomicityMode(TRANSACTIONAL);
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
+
+ qcfg.setIndexPrimitiveKey(true);
+
+ cc.setQueryConfiguration(qcfg);
+
c.setCacheConfiguration(cc);
return c;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedFieldsQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedFieldsQuerySelfTest.java
index 6e80a55..43b0ad5 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedFieldsQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedFieldsQuerySelfTest.java
@@ -17,8 +17,8 @@ import org.jetbrains.annotations.*;
import java.util.*;
-import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCacheDistributionMode.*;
+import static org.gridgain.grid.cache.GridCacheMode.*;
/**
* Tests for fields queries.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedHitsAndMissesSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedHitsAndMissesSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedHitsAndMissesSelfTest.java
index 022a2fd..7cd4d3b 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedHitsAndMissesSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCachePartitionedHitsAndMissesSelfTest.java
@@ -12,18 +12,18 @@ import org.apache.ignite.*;
import org.apache.ignite.configuration.*;
import org.apache.ignite.dataload.*;
import org.apache.ignite.lang.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.cache.*;
import org.apache.ignite.spi.discovery.tcp.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
import org.gridgain.testframework.junits.common.*;
import java.util.*;
-import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCacheDistributionMode.*;
+import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCacheWriteSynchronizationMode.*;
/**
@@ -43,12 +43,6 @@ public class GridCachePartitionedHitsAndMissesSelfTest extends GridCommonAbstrac
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(gridName);
- // IndexingSpi
- GridH2IndexingSpi spi = new GridH2IndexingSpi();
- spi.setName("indexingSpi");
- spi.setDefaultIndexPrimitiveKey(true);
- cfg.setIndexingSpi(spi);
-
// DiscoverySpi
TcpDiscoverySpi disco = new TcpDiscoverySpi();
disco.setIpFinder(IP_FINDER);
@@ -85,6 +79,12 @@ public class GridCachePartitionedHitsAndMissesSelfTest extends GridCommonAbstrac
cfg.setPreloadPartitionedDelay(-1);
cfg.setBackups(1);
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
+
+ qcfg.setIndexPrimitiveKey(true);
+
+ cfg.setQueryConfiguration(qcfg);
+
return cfg;
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheQueryNodeRestartSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheQueryNodeRestartSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheQueryNodeRestartSelfTest.java
index 890fe1d..b3e123f 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheQueryNodeRestartSelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/near/GridCacheQueryNodeRestartSelfTest.java
@@ -12,14 +12,13 @@ package org.gridgain.grid.kernal.processors.cache.distributed.near;
import org.apache.ignite.configuration.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.processors.cache.*;
-import org.apache.ignite.spi.discovery.tcp.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.gridgain.grid.spi.indexing.h2.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
@@ -28,8 +27,8 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import static org.gridgain.grid.cache.GridCacheAtomicityMode.*;
-import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.gridgain.grid.cache.GridCacheDistributionMode.*;
+import static org.gridgain.grid.cache.GridCacheMode.*;
/**
* Test for distributed queries with node restarts.
@@ -72,13 +71,13 @@ public class GridCacheQueryNodeRestartSelfTest extends GridCacheAbstractSelfTest
cc.setAtomicityMode(TRANSACTIONAL);
cc.setDistributionMode(NEAR_PARTITIONED);
- c.setCacheConfiguration(cc);
+ GridCacheQueryConfiguration qcfg = new GridCacheQueryConfiguration();
- GridH2IndexingSpi idxSpi = new GridH2IndexingSpi();
+ qcfg.setIndexPrimitiveKey(true);
- idxSpi.setDefaultIndexPrimitiveKey(true);
+ cc.setQueryConfiguration(qcfg);
- c.setIndexingSpi(idxSpi);
+ c.setCacheConfiguration(cc);
return c;
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedFieldsQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedFieldsQuerySelfTest.java
index 81c1c95..5c2a3ef 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedFieldsQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedFieldsQuerySelfTest.java
@@ -13,12 +13,12 @@ import org.apache.ignite.*;
import org.apache.ignite.cluster.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.future.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
@@ -27,8 +27,8 @@ import org.gridgain.testframework.*;
import java.util.*;
import java.util.concurrent.*;
-import static org.gridgain.grid.cache.GridCacheMode.*;
import static org.apache.ignite.events.IgniteEventType.*;
+import static org.gridgain.grid.cache.GridCacheMode.*;
/**
* Tests for fields queries.
@@ -51,7 +51,7 @@ public class GridCacheReplicatedFieldsQuerySelfTest extends GridCacheAbstractFie
hasCache = true;
try {
- final Map<UUID, Map<Long, GridFutureAdapter<IndexingFieldsResult>>> map =
+ final Map<UUID, Map<Long, GridFutureAdapter<GridQueryFieldsResult>>> map =
U.field(((GridKernal)grid(0)).internalCache().context().queries(), "fieldsQryRes");
// Ensure that iterators map empty.
@@ -82,7 +82,7 @@ public class GridCacheReplicatedFieldsQuerySelfTest extends GridCacheAbstractFie
}
}, getTestTimeout()));
- Map<Long, GridFutureAdapter<IndexingFieldsResult>> futs = map.get(g.cluster().localNode().id());
+ Map<Long, GridFutureAdapter<GridQueryFieldsResult>> futs = map.get(g.cluster().localNode().id());
assertEquals(1, futs.size());
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedQuerySelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedQuerySelfTest.java
index c3da7e0..53d3dfd 100644
--- a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/cache/distributed/replicated/GridCacheReplicatedQuerySelfTest.java
@@ -13,18 +13,16 @@ import org.apache.ignite.*;
import org.apache.ignite.cluster.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.processors.cache.*;
import org.gridgain.grid.kernal.processors.cache.query.*;
+import org.gridgain.grid.util.future.*;
import org.gridgain.grid.util.lang.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.grid.util.future.*;
import org.gridgain.testframework.*;
import org.jetbrains.annotations.*;
import org.springframework.util.*;
@@ -239,7 +237,7 @@ public class GridCacheReplicatedQuerySelfTest extends GridCacheAbstractQuerySelf
* @return {@code qryIters} of {@link GridCacheQueryManager}.
*/
private ConcurrentMap<UUID,
- Map<Long, GridFutureAdapter<GridCloseableIterator<IndexingKeyValueRow<CacheKey, CacheValue>>>>>
+ Map<Long, GridFutureAdapter<GridCloseableIterator<IgniteBiTuple<CacheKey, CacheValue>>>>>
distributedQueryManagerQueryItersMap(Ignite g) {
GridCacheContext ctx = ((GridKernal)g).internalCache().context();
@@ -248,7 +246,7 @@ public class GridCacheReplicatedQuerySelfTest extends GridCacheAbstractQuerySelf
qryItersField.setAccessible(true);
return (ConcurrentMap<UUID,
- Map<Long, GridFutureAdapter<GridCloseableIterator<IndexingKeyValueRow<CacheKey, CacheValue>>>>>)
+ Map<Long, GridFutureAdapter<GridCloseableIterator<IgniteBiTuple<CacheKey, CacheValue>>>>>)
ReflectionUtils.getField(qryItersField, ctx.queries());
}
@@ -397,7 +395,7 @@ public class GridCacheReplicatedQuerySelfTest extends GridCacheAbstractQuerySelf
assertEquals(0, (int)fut.next().getKey());
final ConcurrentMap<UUID, Map<Long, GridFutureAdapter<GridCloseableIterator<
- IndexingKeyValueRow<Integer, Integer>>>>> map =
+ IgniteBiTuple<Integer, Integer>>>>> map =
U.field(((GridKernal)grid(0)).internalCache().context().queries(), "qryIters");
// fut.nextX() does not guarantee the request has completed on remote node
@@ -408,13 +406,13 @@ public class GridCacheReplicatedQuerySelfTest extends GridCacheAbstractQuerySelf
}
}, getTestTimeout()));
- Map<Long, GridFutureAdapter<GridCloseableIterator<IndexingKeyValueRow<Integer, Integer>>>> futs =
+ Map<Long, GridFutureAdapter<GridCloseableIterator<IgniteBiTuple<Integer, Integer>>>> futs =
map.get(g.cluster().localNode().id());
assertEquals(1, futs.size());
- IgniteSpiCloseableIterator<IndexingKeyValueRow<Integer, Integer>> iter =
- U.field(((IgniteFuture)F.first(futs.values()).get()).get(), "iter");
+ GridCloseableIterator<IgniteBiTuple<Integer, Integer>> iter =
+ (GridCloseableIterator<IgniteBiTuple<Integer, Integer>>)((IgniteFuture)F.first(futs.values()).get()).get();
ResultSet rs = U.field(iter, "data");
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexRebuildTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexRebuildTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexRebuildTest.java
new file mode 100644
index 0000000..b288f0b
--- /dev/null
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexRebuildTest.java
@@ -0,0 +1,241 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2;
+
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.lang.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.kernal.processors.query.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.testframework.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ */
+public class GridH2IndexRebuildTest extends GridCacheAbstractSelfTest {
+ /** */
+ private static final int GRID_CNT = 1;
+
+ /** {@inheritDoc} */
+ @Override protected int gridCount() {
+ return GRID_CNT;
+ }
+
+ /**
+ * Overrides rebuildIndexes to check it can be interrupted.
+ */
+ private static class SleepingH2Indexing extends GridH2Indexing {
+ /** */
+ private volatile boolean sleepInRebuild;
+
+ /** */
+ private volatile boolean interrupted;
+
+ /**
+ * Constructor.
+ */
+ public SleepingH2Indexing() {
+ spi = this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void rebuildIndexes(@Nullable String spaceName, GridQueryTypeDescriptor type) {
+ if (sleepInRebuild) {
+ try {
+ U.sleep(Long.MAX_VALUE);
+ }
+ catch (GridInterruptedException ignored) {
+ interrupted = true;
+ }
+ }
+
+ super.rebuildIndexes(spaceName, type);
+ }
+ }
+
+ /** */
+ private static SleepingH2Indexing spi;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ GridQueryProcessor.idxCls = SleepingH2Indexing.class;
+
+ return cfg;
+ }
+
+ /**
+ * Value class with regular and compound indexes.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ private static class TestValue1 {
+ /** */
+ @GridCacheQuerySqlField(index = true)
+ private long val1;
+
+ /** */
+ @GridCacheQuerySqlField(index = true)
+ private String val2;
+
+ /** */
+ @GridCacheQuerySqlField(groups = "group1")
+ private int val3;
+
+ /** */
+ @GridCacheQuerySqlField(groups = "group1")
+ private int val4;
+
+ /**
+ */
+ TestValue1(long val1, String val2, int val3, int val4) {
+ this.val1 = val1;
+ this.val2 = val2;
+ this.val3 = val3;
+ this.val4 = val4;
+ }
+ }
+
+ /**
+ * Value class with regular and text indexes.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ private static class TestValue2 {
+ /** */
+ @GridCacheQuerySqlField(index = true)
+ private long val1;
+
+ /** */
+ @GridCacheQueryTextField
+ private String val2;
+
+ /**
+ */
+ TestValue2(long val1, String val2) {
+ this.val1 = val1;
+ this.val2 = val2;
+ }
+ }
+
+ /** */
+ private static final int ENTRY_CNT = 10000;
+
+ /**
+ * @throws Exception if failed.
+ */
+ public void testRebuildIndexes() throws Exception {
+ cache().queries().rebuildIndexes(ArrayList.class).get();
+
+ cache().queries().rebuildAllIndexes().get();
+
+ GridCache<Integer, TestValue1> cache1 = grid(0).cache(null);
+ GridCache<Integer, TestValue2> cache2 = grid(0).cache(null);
+
+ for (int i = 0; i < ENTRY_CNT; i++) {
+ cache1.put(i, new TestValue1(i, "val2-" + i, i, i));
+ cache2.put(ENTRY_CNT * 2 + i, new TestValue2(i, "val2-" + i));
+ }
+
+ GridCacheQuery<Map.Entry<Integer, TestValue1>> qry1 =
+ cache1.queries().createSqlQuery(TestValue1.class, "val1 = 9000");
+
+ GridCacheQuery<Map.Entry<Integer, TestValue1>> qry2 =
+ cache1.queries().createSqlQuery(TestValue1.class, "val2 = 'val2-9000'");
+
+ GridCacheQuery<Map.Entry<Integer, TestValue1>> qry3 =
+ cache1.queries().createSqlQuery(TestValue1.class, "val3 = 9000 and val4 = 9000");
+
+ GridCacheQuery<Map.Entry<Integer, TestValue2>> qry4 =
+ cache2.queries().createSqlQuery(TestValue2.class, "val1 = 9000");
+
+ GridCacheQuery<Map.Entry<Integer, TestValue2>> qry5 =
+ cache2.queries().createFullTextQuery(TestValue2.class, "val2 = 'val2-9000'");
+
+ checkQueryReturnsOneEntry(qry1, qry2, qry3, qry4, qry5);
+
+ for (int i = 0; i < ENTRY_CNT / 2; i++) {
+ cache1.remove(i);
+ cache2.remove(ENTRY_CNT * 2 + i);
+ }
+
+ cache().queries().rebuildIndexes(TestValue1.class).get();
+ cache().queries().rebuildIndexes(TestValue2.class).get();
+
+ checkQueryReturnsOneEntry(qry1, qry2, qry3, qry4, qry5);
+
+ cache().queries().rebuildAllIndexes().get();
+
+ checkQueryReturnsOneEntry(qry1, qry2, qry3, qry4, qry5);
+ }
+
+ /**
+ * @throws Exception if failed.
+ */
+ public void testRebuildInterrupted() throws Exception {
+ spi.sleepInRebuild = true;
+
+ GridCache<Integer, TestValue1> cache1 = grid(0).cache(null);
+ GridCache<Integer, TestValue2> cache2 = grid(0).cache(null);
+
+ cache1.put(0, new TestValue1(0, "val0", 0 ,0));
+ cache2.put(1, new TestValue2(0, "val0"));
+
+ checkCancel(grid(0).cache(null).queries().rebuildIndexes("TestValue1"));
+
+ checkCancel(grid(0).cache(null).queries().rebuildAllIndexes());
+
+ spi.sleepInRebuild = false;
+
+ final IgniteFuture<?> fut1 = grid(0).cache(null).queries().rebuildIndexes(TestValue1.class);
+
+ assertFalse(fut1.isCancelled());
+
+ fut1.get();
+
+ final IgniteFuture<?> fut2 = grid(0).cache(null).queries().rebuildAllIndexes();
+
+ assertFalse(fut2.isCancelled());
+
+ fut2.get();
+ }
+
+ /**
+ * @throws Exception if failed.
+ */
+ private void checkCancel(final IgniteFuture<?> fut) throws Exception {
+ assertTrue(fut.cancel());
+
+ GridTestUtils.assertThrows(log, new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ fut.get();
+ return null;
+ }
+ }, IgniteFutureCancelledException.class, null);
+
+ assertTrue(spi.interrupted);
+
+ spi.interrupted = false;
+ }
+
+ /**
+ * @throws Exception if failed.
+ */
+ private void checkQueryReturnsOneEntry(GridCacheQuery<?>... qrys) throws Exception {
+ for (GridCacheQuery<?> qry : qrys)
+ assertEquals(1, qry.execute().get().size());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingGeoSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingGeoSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingGeoSelfTest.java
new file mode 100644
index 0000000..1f22529
--- /dev/null
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingGeoSelfTest.java
@@ -0,0 +1,240 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2;
+
+import com.vividsolutions.jts.geom.*;
+import com.vividsolutions.jts.io.*;
+import org.apache.ignite.lang.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.testframework.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ *
+ */
+public class GridH2IndexingGeoSelfTest extends GridCacheAbstractSelfTest {
+ /** */
+ private static final int CNT = 100;
+
+ /** */
+ private static final long DUR = 60000L;
+
+ /** {@inheritDoc} */
+ @Override protected int gridCount() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long getTestTimeout() {
+ return DUR * 3;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @SuppressWarnings("unchecked")
+ public void testGeo() throws Exception {
+ GridCache<Integer, EnemyCamp> cache = grid(0).cache(null);
+
+ WKTReader r = new WKTReader();
+
+ cache.put(0, new EnemyCamp(r.read("POINT(25 75)"), "A"));
+ cache.put(1, new EnemyCamp(r.read("POINT(70 70)"), "B"));
+ cache.put(2, new EnemyCamp(r.read("POINT(70 30)"), "C"));
+ cache.put(3, new EnemyCamp(r.read("POINT(75 25)"), "D"));
+
+ GridCacheQuery<Map.Entry<Integer, EnemyCamp>> qry = cache.queries().createSqlQuery(EnemyCamp.class,
+ "coords && ?");
+
+ Collection<Map.Entry<Integer, EnemyCamp>> res = qry.execute(r.read("POLYGON((5 70, 5 80, 30 80, 30 70, 5 70))"))
+ .get();
+
+ checkPoints(res, "A");
+
+ res = qry.execute(r.read("POLYGON((10 5, 10 35, 70 30, 75 25, 10 5))")).get();
+
+ checkPoints(res, "C", "D");
+
+ // Move B to the first polygon.
+ cache.put(1, new EnemyCamp(r.read("POINT(20 75)"), "B"));
+
+ res = qry.execute(r.read("POLYGON((5 70, 5 80, 30 80, 30 70, 5 70))")).get();
+
+ checkPoints(res, "A", "B");
+
+ // Move B to the second polygon.
+ cache.put(1, new EnemyCamp(r.read("POINT(30 30)"), "B"));
+
+ res = qry.execute(r.read("POLYGON((10 5, 10 35, 70 30, 75 25, 10 5))")).get();
+
+ checkPoints(res, "B", "C", "D");
+
+ // Remove B.
+ cache.remove(1);
+
+ res = qry.execute(r.read("POLYGON((5 70, 5 80, 30 80, 30 70, 5 70))")).get();
+
+ checkPoints(res, "A");
+
+ res = qry.execute(r.read("POLYGON((10 5, 10 35, 70 30, 75 25, 10 5))")).get();
+
+ checkPoints(res, "C", "D");
+
+ // Check explaint request.
+ assertTrue(F.first(cache.queries().createSqlFieldsQuery("explain select * from EnemyCamp " +
+ "where coords && 'POINT(25 75)'").execute().get()).get(0).toString().contains("coords_idx"));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @SuppressWarnings("unchecked")
+ public void testGeoMultithreaded() throws Exception {
+ final GridCache<Integer, EnemyCamp> cache1 = grid(0).cache(null);
+ final GridCache<Integer, EnemyCamp> cache2 = grid(1).cache(null);
+ final GridCache<Integer, EnemyCamp> cache3 = grid(2).cache(null);
+
+ final String[] points = new String[CNT];
+
+ WKTReader r = new WKTReader();
+
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ for (int idx = 0; idx < CNT; idx++) {
+ int x = rnd.nextInt(1, 100);
+ int y = rnd.nextInt(1, 100);
+
+ cache1.put(idx, new EnemyCamp(r.read("POINT(" + x + " " + y + ")"), Integer.toString(idx)));
+
+ points[idx] = Integer.toString(idx);
+ }
+
+ Thread.sleep(200);
+
+ final AtomicBoolean stop = new AtomicBoolean();
+ final AtomicReference<Exception> err = new AtomicReference<>();
+
+ IgniteFuture<?> putFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ WKTReader r = new WKTReader();
+
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ while (!stop.get()) {
+ int cacheIdx = rnd.nextInt(0, 3);
+
+ GridCache<Integer, EnemyCamp> cache = cacheIdx == 0 ? cache1 : cacheIdx == 1 ? cache2 : cache3;
+
+ int idx = rnd.nextInt(CNT);
+ int x = rnd.nextInt(1, 100);
+ int y = rnd.nextInt(1, 100);
+
+ cache.put(idx, new EnemyCamp(r.read("POINT(" + x + " " + y + ")"), Integer.toString(idx)));
+
+ U.sleep(50);
+ }
+
+ return null;
+ }
+ }, Runtime.getRuntime().availableProcessors(), "put-thread");
+
+ IgniteFuture<?> qryFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ WKTReader r = new WKTReader();
+
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ while (!stop.get()) {
+ try {
+ int cacheIdx = rnd.nextInt(0, 3);
+
+ GridCache<Integer, EnemyCamp> cache = cacheIdx == 0 ? cache1 : cacheIdx == 1 ? cache2 : cache3;
+
+ GridCacheQuery<Map.Entry<Integer, EnemyCamp>> qry = cache.queries().createSqlQuery(
+ EnemyCamp.class, "coords && ?");
+
+ Collection<Map.Entry<Integer, EnemyCamp>> res = qry.execute(
+ r.read("POLYGON((0 0, 0 100, 100 100, 100 0, 0 0))")).get();
+
+ checkPoints(res, points);
+
+ U.sleep(5);
+ }
+ catch (Exception e) {
+ err.set(e);
+
+ stop.set(true);
+
+ break;
+ }
+ }
+
+ return null;
+ }
+ }, 4, "qry-thread");
+
+ U.sleep(60000L);
+
+ stop.set(true);
+
+ putFut.get();
+ qryFut.get();
+
+ Exception err0 = err.get();
+
+ if (err0 != null)
+ throw err0;
+ }
+
+ /**
+ * Check whether result contains all required points.
+ *
+ * @param res Result.
+ * @param points Expected points.
+ */
+ private void checkPoints( Collection<Map.Entry<Integer, EnemyCamp>> res, String... points) {
+ Set<String> set = new HashSet<>(Arrays.asList(points));
+
+ assertEquals(set.size(), res.size());
+
+ for (Map.Entry<Integer, EnemyCamp> e : res)
+ assertTrue(set.remove(e.getValue().name));
+ }
+
+ /**
+ *
+ */
+ private static class EnemyCamp implements Serializable {
+ /** */
+ @GridCacheQuerySqlField(index = true)
+ private Geometry coords;
+
+ /** */
+ @GridCacheQuerySqlField
+ private String name;
+
+ /**
+ * @param coords Coordinates.
+ * @param name Name.
+ */
+ private EnemyCamp(Geometry coords, String name) {
+ this.coords = coords;
+ this.name = name;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingInMemSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingInMemSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingInMemSelfTest.java
new file mode 100644
index 0000000..ced0025
--- /dev/null
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingInMemSelfTest.java
@@ -0,0 +1,17 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2;
+
+/**
+ * Tests for H2 indexing SPI.
+ */
+public class GridH2IndexingInMemSelfTest extends GridIndexingSpiAbstractSelfTest {
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingOffheapSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingOffheapSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingOffheapSelfTest.java
new file mode 100644
index 0000000..45aee5d
--- /dev/null
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridH2IndexingOffheapSelfTest.java
@@ -0,0 +1,36 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2;
+
+/**
+ * Tests for H2 indexing SPI.
+ */
+public class GridH2IndexingOffheapSelfTest extends GridIndexingSpiAbstractSelfTest {
+ /** */
+ private static final long offheap = 10000000;
+
+ private static GridH2Indexing currentSpi;
+
+ /** {@inheritDoc} */
+ @Override protected void startIndexing(GridH2Indexing spi) throws Exception {
+ spi.configuration().setMaxOffHeapMemory(offheap);
+
+ currentSpi = spi;
+
+ super.startIndexing(spi);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ super.afterTestsStopped();
+
+ assertEquals(0, currentSpi.getAllocatedOffHeapMemory());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
new file mode 100644
index 0000000..135fd62
--- /dev/null
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
@@ -0,0 +1,553 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2;
+
+import org.apache.ignite.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.*;
+import org.gridgain.grid.kernal.processors.query.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.spi.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.testframework.*;
+import org.gridgain.testframework.junits.common.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Tests for all SQL based indexing SPI implementations.
+ */
+public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstractTest {
+ /** */
+ private static final TextIndex textIdx = new TextIndex(F.asList("txt"));
+
+ /** */
+ private static final Map<String, Class<?>> fieldsAA = new HashMap<>();
+
+ /** */
+ private static final Map<String, Class<?>> fieldsAB = new HashMap<>();
+
+ /** */
+ private static final Map<String, Class<?>> fieldsBA = new HashMap<>();
+
+ /**
+ * Fields initialization.
+ */
+ static {
+ fieldsAA.put("id", Long.class);
+ fieldsAA.put("name", String.class);
+ fieldsAA.put("age", Integer.class);
+
+ fieldsAB.putAll(fieldsAA);
+ fieldsAB.put("txt", String.class);
+
+ fieldsBA.putAll(fieldsAA);
+ fieldsBA.put("sex", Boolean.class);
+ }
+
+ /** */
+ private static TypeDesc typeAA = new TypeDesc("A", "A", fieldsAA, null);
+
+ /** */
+ private static TypeDesc typeAB = new TypeDesc("A", "B", fieldsAB, textIdx);
+
+ /** */
+ private static TypeDesc typeBA = new TypeDesc("B", "A", fieldsBA, null);
+
+ /** */
+ private GridH2Indexing idx = new GridH2Indexing();
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ getTestResources().inject(idx);
+
+ startIndexing(idx);
+ }
+
+ /** {@inheritDoc} */
+ protected void startIndexing(GridH2Indexing spi) throws Exception {
+ spi.registerSpace("A");
+ spi.registerSpace("B");
+
+ spi.start(null);
+ }
+
+ @Override protected void afterTest() throws Exception {
+ idx.stop();
+
+ idx = null;
+ }
+
+ /**
+ * @param id Id.
+ * @param name Name.
+ * @param age Age.
+ * @return AA.
+ */
+ private Map<String, Object> aa(long id, String name, int age) {
+ Map<String, Object> map = new HashMap<>();
+
+ map.put("id", id);
+ map.put("name", name);
+ map.put("age", age);
+
+ return map;
+ }
+
+ /**
+ * @param id Id.
+ * @param name Name.
+ * @param age Age.
+ * @param txt Text.
+ * @return AB.
+ */
+ private Map<String, Object> ab(long id, String name, int age, String txt) {
+ Map<String, Object> map = aa(id, name, age);
+
+ map.put("txt", txt);
+
+ return map;
+ }
+
+ /**
+ * @param id Id.
+ * @param name Name.
+ * @param age Age.
+ * @param sex Sex.
+ * @return BA.
+ */
+ private Map<String, Object> ba(long id, String name, int age, boolean sex) {
+ Map<String, Object> map = aa(id, name, age);
+
+ map.put("sex", sex);
+
+ return map;
+ }
+
+ /**
+ * @param row Row
+ * @return Value.
+ * @throws IgniteSpiException If failed.
+ */
+ private Map<String, Object> value(IgniteBiTuple<Integer, Map<String, Object>> row) throws IgniteSpiException {
+ return row.get2();
+ }
+
+ /**
+ * @return Indexing.
+ */
+ private GridH2Indexing getIndexing() {
+ return idx;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testSpi() throws Exception {
+ GridH2Indexing spi = getIndexing();
+
+ assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(-1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(-1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.registerType(typeAA.space(), typeAA);
+
+ assertEquals(0, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(-1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(-1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.registerType(typeAB.space(), typeAB);
+
+ assertEquals(0, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(0, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(-1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.registerType(typeBA.space(), typeBA);
+
+ // Initially all is empty.
+ assertEquals(0, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(0, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+
+ assertFalse(spi.query(typeAA.space(), "select * from A.A", Collections.emptySet(), typeAA, null).hasNext());
+ assertFalse(spi.query(typeAB.space(), "select * from A.B", Collections.emptySet(), typeAB, null).hasNext());
+ assertFalse(spi.query(typeBA.space(), "select * from B.A", Collections.emptySet(), typeBA, null).hasNext());
+
+ // Nothing to remove.
+ spi.remove("A", 1);
+ spi.remove("B", 1);
+
+ spi.store(typeAA.space(), typeAA, 1, aa(1, "Vasya", 10), "v1".getBytes(), 0);
+
+ assertEquals(1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(0, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+
+ spi.store(typeAB.space(), typeAB, 1, ab(1, "Vasya", 20, "Some text about Vasya goes here."),
+ "v2".getBytes(), 0);
+
+ // In one space all keys must be unique.
+ assertEquals(0, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+
+ spi.store(typeBA.space(), typeBA, 1, ba(2, "Petya", 25, true), "v3".getBytes(), 0);
+
+ // No replacement because of different space.
+ assertEquals(0, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.store(typeBA.space(), typeBA, 1, ba(2, "Kolya", 25, true), "v4".getBytes(), 0);
+
+ // Replacement in the same table.
+ assertEquals(0, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.store(typeAA.space(), typeAA, 2, aa(2, "Valera", 19), "v5".getBytes(), 0);
+
+ assertEquals(1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.store(typeAA.space(), typeAA, 3, aa(3, "Borya", 18), "v6".getBytes(), 0);
+
+ assertEquals(2, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.store(typeAB.space(), typeAB, 4, ab(4, "Vitalya", 20, "Very Good guy"), "v7".getBytes(), 0);
+
+ assertEquals(2, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(2, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+
+ // Query data.
+ Iterator<IgniteBiTuple<Integer, Map<String, Object>>> res =
+ spi.query(typeAA.space(), "select * from a order by age", Collections.emptySet(), typeAA, null);
+
+ assertTrue(res.hasNext());
+ assertEquals(aa(3, "Borya", 18), value(res.next()));
+ assertTrue(res.hasNext());
+ assertEquals(aa(2, "Valera", 19), value(res.next()));
+ assertFalse(res.hasNext());
+
+ res = spi.query(typeAB.space(), "select * from b order by name", Collections.emptySet(), typeAB, null);
+
+ assertTrue(res.hasNext());
+ assertEquals(ab(1, "Vasya", 20, "Some text about Vasya goes here."), value(res.next()));
+ assertTrue(res.hasNext());
+ assertEquals(ab(4, "Vitalya", 20, "Very Good guy"), value(res.next()));
+ assertFalse(res.hasNext());
+
+ res = spi.query(typeBA.space(), "select * from a", Collections.emptySet(), typeBA, null);
+
+ assertTrue(res.hasNext());
+ assertEquals(ba(2, "Kolya", 25, true), value(res.next()));
+ assertFalse(res.hasNext());
+
+ // Text queries
+ Iterator<IgniteBiTuple<Integer, Map<String, Object>>> txtRes = spi.queryText(typeAB.space(), "good",
+ typeAB, null);
+
+ assertTrue(txtRes.hasNext());
+ assertEquals(ab(4, "Vitalya", 20, "Very Good guy"), value(txtRes.next()));
+ assertFalse(txtRes.hasNext());
+
+ // Fields query
+ GridQueryFieldsResult fieldsRes =
+ spi.queryFields(null, "select a.a.name n1, a.a.age a1, b.a.name n2, " +
+ "b.a.age a2 from a.a, b.a where a.a.id = b.a.id ", Collections.emptySet(), null);
+
+ String[] aliases = {"N1", "A1", "N2", "A2"};
+ Object[] vals = { "Valera", 19, "Kolya", 25};
+
+ assertTrue(fieldsRes.iterator().hasNext());
+
+ List<?> fields = fieldsRes.iterator().next();
+
+ assertEquals(4, fields.size());
+
+ int i = 0;
+
+ for (Object f : fields) {
+ assertEquals(aliases[i], fieldsRes.metaData().get(i).fieldName());
+ assertEquals(vals[i++], f);
+ }
+
+ assertFalse(fieldsRes.iterator().hasNext());
+
+ // Query on not existing table should not fail.
+ assertFalse(spi.queryFields(null, "select * from not_existing_table",
+ Collections.emptySet(), null).iterator().hasNext());
+
+ // Remove
+ spi.remove(typeAA.space(), 2);
+
+ assertEquals(1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(2, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+
+ spi.remove(typeBA.space(), 1);
+
+ assertEquals(1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(2, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+
+ boolean h2IdxOffheap = spi.configuration().getMaxOffHeapMemory() > 0;
+
+ // At the time of this writing index rebuilding is not supported for GridH2Indexing with off-heap storage.
+ if (!h2IdxOffheap) {
+ // Rebuild
+
+ spi.rebuildIndexes(typeAB.space(), typeAB);
+
+ assertEquals(1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(2, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+
+ // For invalid space name/type should not fail.
+ spi.rebuildIndexes("not_existing_space", typeAA);
+ spi.rebuildIndexes(typeAA.space(), new TypeDesc("C", "C", fieldsAA, null));
+ }
+
+ // Unregister.
+ spi.unregisterType(typeAA.space(), typeAA);
+
+ assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(2, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+
+ spi.unregisterType(typeAB.space(), typeAB);
+
+ assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(-1, spi.size(typeAB.space(), typeAB, null));
+ assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+
+ spi.unregisterType(typeBA.space(), typeBA);
+
+ // Should not store but should not fail as well.
+ spi.store(typeAA.space(), typeAA, 10, aa(1, "Fail", 100500), "v220".getBytes(), 0);
+
+ assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
+ }
+
+ /**
+ * Test long queries write explain warnings into log.
+ *
+ * @throws Exception If failed.
+ */
+ public void testLongQueries() throws Exception {
+ GridH2Indexing spi = getIndexing();
+
+ long longQryExecTime = 100;
+
+ GridStringLogger log = new GridStringLogger(false, this.log);
+
+ IgniteLogger oldLog = GridTestUtils.getFieldValue(spi, "log");
+
+ spi.configuration().setLongQueryExecutionTimeout(longQryExecTime);
+ spi.configuration().setLongQueryExplain(true);
+
+ try {
+ GridTestUtils.setFieldValue(spi, "log", log);
+
+ String sql = "select sum(x) FROM SYSTEM_RANGE(?, ?)";
+
+ long now = U.currentTimeMillis();
+ long time = now;
+
+ long range = 1000000L;
+
+ while (now - time <= longQryExecTime * 3 / 2) {
+ time = now;
+ range *= 3;
+
+ GridQueryFieldsResult res = spi.queryFields(null, sql, Arrays.<Object>asList(1, range), null);
+
+ assert res.iterator().hasNext();
+
+ now = U.currentTimeMillis();
+ }
+
+ String res = log.toString();
+
+ F.println(res);
+
+ assert res.contains("/* PUBLIC.RANGE_INDEX */");
+ }
+ finally {
+ GridTestUtils.setFieldValue(spi, "log", oldLog);
+ spi.configuration().setLongQueryExecutionTimeout(3000);
+ }
+ }
+
+ public void _testResultReuse() throws Exception {
+ final GridH2Indexing spi = getIndexing();
+
+ multithreaded(new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ return spi.queryFields(null, "SELECT sum(x) + sum(x) + sum(x) + sum(x) FROM SYSTEM_RANGE(?, ?)",
+ F.<Object>asList(0, 7000000), null);
+ }
+ }, 5);
+ }
+
+ /**
+ * Test long queries write explain warnings into log.
+ *
+ * @throws Exception If failed.
+ */
+ public void testZeroLongQuery() throws Exception {
+ GridH2Indexing spi = getIndexing();
+
+ long longQryExecTime = -1;
+
+ GridStringLogger log = new GridStringLogger(false, this.log);
+
+ IgniteLogger oldLog = GridTestUtils.getFieldValue(spi, "log");
+ spi.configuration().setLongQueryExecutionTimeout(longQryExecTime);
+ spi.configuration().setLongQueryExplain(true);
+
+ try {
+ GridTestUtils.setFieldValue(spi, "log", log);
+
+ String sql = "SELECT * FROM MyNonExistingTable";
+
+ GridQueryFieldsResult res = spi.queryFields(null, sql, Collections.emptyList(), null);
+
+ assertFalse(res.iterator().hasNext());
+
+ String logStr = log.toString();
+
+ F.println(logStr);
+
+ assertTrue(logStr.contains("Failed to explain plan because required table does not exist"));
+ }
+ finally {
+ GridTestUtils.setFieldValue(spi, "log", oldLog);
+ spi.configuration().setLongQueryExecutionTimeout(3000);
+ }
+ }
+
+ /**
+ * Index descriptor.
+ */
+ private static class TextIndex implements GridQueryIndexDescriptor {
+ /** */
+ private final Collection<String> fields;
+
+ /**
+ * @param fields Fields.
+ */
+ private TextIndex(Collection<String> fields) {
+ this.fields = Collections.unmodifiableCollection(fields);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Collection<String> fields() {
+ return fields;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean descending(String field) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridQueryIndexType type() {
+ return GridQueryIndexType.FULLTEXT;
+ }
+ }
+
+ /**
+ * Type descriptor.
+ */
+ private static class TypeDesc implements GridQueryTypeDescriptor {
+ /** */
+ private final String name;
+
+ /** */
+ private final String space;
+
+ /** */
+ private final Map<String, Class<?>> valFields;
+
+ /** */
+ private final GridQueryIndexDescriptor textIdx;
+
+ /**
+ * @param space Space name.
+ * @param name Type name.
+ * @param valFields Fields.
+ * @param textIdx Fulltext index.
+ */
+ private TypeDesc(String space, String name, Map<String, Class<?>> valFields, GridQueryIndexDescriptor textIdx) {
+ this.name = name;
+ this.space = space;
+ this.valFields = Collections.unmodifiableMap(valFields);
+ this.textIdx = textIdx;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String name() {
+ return name;
+ }
+
+ /**
+ * @return Space name.
+ */
+ public String space() {
+ return space;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Map<String, Class<?>> valueFields() {
+ return valFields;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Map<String, Class<?>> keyFields() {
+ return Collections.emptyMap();
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> T value(Object obj, String field) throws IgniteSpiException {
+ assert obj != null;
+ assert !F.isEmpty(field);
+
+ return (T)((Map<String, Object>) obj).get(field);
+ }
+
+ /** */
+ @Override public Map<String, GridQueryIndexDescriptor> indexes() {
+ return textIdx == null ? Collections.<String, GridQueryIndexDescriptor>emptyMap() :
+ Collections.singletonMap("index", textIdx);
+ }
+
+ /** */
+ @Override public Class<?> valueClass() {
+ return Object.class;
+ }
+
+ /** */
+ @Override public Class<?> keyClass() {
+ return Integer.class;
+ }
+
+ /** */
+ @Override public boolean valueTextIndex() {
+ return textIdx == null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TableSelfTest.java b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TableSelfTest.java
new file mode 100644
index 0000000..6d2f75c
--- /dev/null
+++ b/modules/indexing/src/test/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TableSelfTest.java
@@ -0,0 +1,613 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.gridgain.testframework.junits.common.*;
+import org.h2.Driver;
+import org.h2.index.*;
+import org.h2.result.*;
+import org.h2.table.*;
+import org.h2.value.*;
+import org.jetbrains.annotations.*;
+import org.junit.*;
+
+import java.sql.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * Tests H2 Table.
+ */
+@SuppressWarnings({"TypeMayBeWeakened", "FieldAccessedSynchronizedAndUnsynchronized"})
+public class GridH2TableSelfTest extends GridCommonAbstractTest {
+ /** */
+ private static final long MAX_X = 2000;
+
+ /** */
+ private static final String DB_URL = "jdbc:h2:mem:gg_table_engine;MULTI_THREADED=1;OPTIMIZE_REUSE_RESULTS=0;" +
+ "QUERY_CACHE_SIZE=0;RECOMPILE_ALWAYS=1";
+
+ /** */
+ private static final String CREATE_TABLE_SQL = "CREATE TABLE T(ID UUID, T TIMESTAMP, STR VARCHAR, X BIGINT)";
+
+ /** */
+ private static final String PK_NAME = "__GG_PK_";
+
+ /** */
+ private static final String STR_IDX_NAME = "__GG_IDX_";
+
+ /** */
+ private static final String NON_UNIQUE_IDX_NAME = "__GG_IDX_";
+
+ /** */
+ private static final String SCAN_IDX_NAME = GridH2Table.ScanIndex.SCAN_INDEX_NAME_SUFFIX;
+
+ /** */
+ private Connection conn;
+
+ /** */
+ private GridH2Table tbl;
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ Driver.load();
+
+ conn = DriverManager.getConnection(DB_URL);
+
+ tbl = GridH2Table.Engine.createTable(conn, CREATE_TABLE_SQL, null, new GridH2Table.IndexesFactory() {
+ @Override public ArrayList<Index> createIndexes(GridH2Table tbl) {
+ ArrayList<Index> idxs = new ArrayList<>();
+
+ IndexColumn id = tbl.indexColumn(0, SortOrder.ASCENDING);
+ IndexColumn t = tbl.indexColumn(1, SortOrder.ASCENDING);
+ IndexColumn str = tbl.indexColumn(2, SortOrder.DESCENDING);
+ IndexColumn x = tbl.indexColumn(3, SortOrder.DESCENDING);
+
+ idxs.add(new GridH2TreeIndex(PK_NAME, tbl, true, 0, 1, id));
+ idxs.add(new GridH2TreeIndex(NON_UNIQUE_IDX_NAME, tbl, false, 0, 1, x, t));
+ idxs.add(new GridH2TreeIndex(STR_IDX_NAME, tbl, false, 0, 1, str));
+
+ return idxs;
+ }
+ }, null);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ conn.close();
+
+ conn = null;
+ tbl = null;
+ }
+
+ /**
+ * @param id Id.
+ * @param t Timestamp.
+ * @param str String.
+ * @param x X.
+ * @return New row.
+ */
+ private GridH2Row row(UUID id, long t, String str, long x) {
+ return new GridH2Row(ValueUuid.get(id.getMostSignificantBits(), id.getLeastSignificantBits()),
+ ValueTimestamp.get(new Timestamp(t)),
+ ValueString.get(str),
+ ValueLong.get(x));
+ }
+
+
+ /**
+ * Simple table test.
+ *
+ * @throws Exception If failed.
+ */
+ public void testTable() throws Exception {
+ // Test insert.
+ long x = MAX_X;
+
+ Random rnd = new Random();
+
+ while(x-- > 0) {
+ UUID id = UUID.randomUUID();
+
+ GridH2Row row = row(id, System.currentTimeMillis(), rnd.nextBoolean() ? id.toString() :
+ UUID.randomUUID().toString(), rnd.nextInt(100));
+
+ tbl.doUpdate(row, false);
+ }
+
+ assertEquals(MAX_X, tbl.getRowCountApproximation());
+ assertEquals(MAX_X, tbl.getRowCount(null));
+
+ for (GridH2IndexBase idx : tbl.indexes()) {
+ assertEquals(MAX_X, idx.getRowCountApproximation());
+ assertEquals(MAX_X, idx.getRowCount(null));
+ }
+
+ // Check correct rows order.
+ checkOrdered((GridH2TreeIndex)tbl.indexes().get(0), new Comparator<SearchRow>() {
+ @Override public int compare(SearchRow o1, SearchRow o2) {
+ UUID id1 = (UUID)o1.getValue(0).getObject();
+ UUID id2 = (UUID)o2.getValue(0).getObject();
+
+ return id1.compareTo(id2);
+ }
+ });
+
+ checkOrdered((GridH2TreeIndex)tbl.indexes().get(1), new Comparator<SearchRow>() {
+ @Override public int compare(SearchRow o1, SearchRow o2) {
+ Long x1 = (Long)o1.getValue(3).getObject();
+ Long x2 = (Long)o2.getValue(3).getObject();
+
+ int c = x2.compareTo(x1);
+
+ if (c != 0)
+ return c;
+
+ Timestamp t1 = (Timestamp)o1.getValue(1).getObject();
+ Timestamp t2 = (Timestamp)o2.getValue(1).getObject();
+
+ return t1.compareTo(t2);
+ }
+ });
+
+ checkOrdered((GridH2TreeIndex)tbl.indexes().get(2), new Comparator<SearchRow>() {
+ @Override public int compare(SearchRow o1, SearchRow o2) {
+ String s1 = (String)o1.getValue(2).getObject();
+ String s2 = (String)o2.getValue(2).getObject();
+
+ return s2.compareTo(s1);
+ }
+ });
+
+ // Indexes data consistency.
+ ArrayList<? extends Index> idxs = tbl.indexes();
+
+ checkIndexesConsistent((ArrayList<Index>)idxs, null);
+
+ // Check unique index.
+ UUID id = UUID.randomUUID();
+ UUID id2 = UUID.randomUUID();
+
+ assertTrue(tbl.doUpdate(row(id, System.currentTimeMillis(), id.toString(), rnd.nextInt(100)), false));
+ assertTrue(tbl.doUpdate(row(id2, System.currentTimeMillis(), id2.toString(), rnd.nextInt(100)), false));
+
+ // Check index selection.
+ checkQueryPlan(conn, "SELECT * FROM T", SCAN_IDX_NAME);
+
+ checkQueryPlan(conn, "SELECT * FROM T WHERE ID IS NULL", PK_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T WHERE ID = RANDOM_UUID()", PK_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T WHERE ID > RANDOM_UUID()", PK_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T ORDER BY ID", PK_NAME);
+
+ checkQueryPlan(conn, "SELECT * FROM T WHERE STR IS NULL", STR_IDX_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T WHERE STR = 'aaaa'", STR_IDX_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T WHERE STR > 'aaaa'", STR_IDX_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T ORDER BY STR DESC", STR_IDX_NAME);
+
+ checkQueryPlan(conn, "SELECT * FROM T WHERE X IS NULL", NON_UNIQUE_IDX_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T WHERE X = 10000", NON_UNIQUE_IDX_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T WHERE X > 10000", NON_UNIQUE_IDX_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T ORDER BY X DESC", NON_UNIQUE_IDX_NAME);
+ checkQueryPlan(conn, "SELECT * FROM T ORDER BY X DESC, T", NON_UNIQUE_IDX_NAME);
+
+ checkQueryPlan(conn, "SELECT * FROM T ORDER BY T, X DESC", SCAN_IDX_NAME);
+
+ // Simple queries.
+
+ Statement s = conn.createStatement();
+
+ ResultSet rs = s.executeQuery("select id from t where x between 0 and 100");
+
+ int i = 0;
+ while (rs.next())
+ i++;
+
+ assertEquals(MAX_X + 2, i);
+
+ // -----
+
+ rs = s.executeQuery("select id from t where t is not null");
+
+ i = 0;
+ while (rs.next())
+ i++;
+
+ assertEquals(MAX_X + 2, i);
+
+ // ----
+
+ int cnt = 10 + rnd.nextInt(25);
+
+ long t = System.currentTimeMillis();
+
+ for (i = 0; i < cnt; i++) {
+ id = UUID.randomUUID();
+
+ assertTrue(tbl.doUpdate(row(id, t, id.toString(), 51), false));
+ }
+
+ rs = s.executeQuery("select x, id from t where x = 51 limit " + cnt);
+
+ i = 0;
+
+ while (rs.next()) {
+ assertEquals(51, rs.getInt(1));
+
+ i++;
+ }
+
+ assertEquals(cnt, i);
+ }
+
+ /**
+ * Dumps all table rows for index.
+ *
+ * @param idx Index.
+ */
+ private void dumpRows(GridH2TreeIndex idx) {
+ Iterator<GridH2Row> iter = idx.rows();
+
+ while (iter.hasNext())
+ System.out.println(iter.next().toString());
+ }
+
+ /**
+ * Multithreaded indexes consistency test.
+ *
+ * @throws Exception If failed.
+ */
+ public void testIndexesMultiThreadedConsistency() throws Exception {
+ final int threads = 19;
+ final int iterations = 1500;
+
+ multithreaded(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ Random rnd = new Random();
+
+ PreparedStatement ps1 = null;
+
+ for (int i = 0; i < iterations; i++) {
+ UUID id = UUID.randomUUID();
+
+ int x = rnd.nextInt(50);
+
+ long t = System.currentTimeMillis();
+
+ GridH2Row row = row(id, t, rnd.nextBoolean() ? id.toString() : UUID.randomUUID().toString(), x);
+
+ assertTrue(tbl.doUpdate(row, false));
+
+ if (rnd.nextInt(100) == 0) {
+ tbl.lock(null, false, false);
+
+ long cnt = 0;
+
+ try {
+ ArrayList<Index> idxs = tbl.getIndexes();
+
+ // Consistency check.
+ Set<Row> rowSet = checkIndexesConsistent(idxs, null);
+
+ // Order check.
+ checkOrdered(idxs);
+
+ checkIndexesConsistent(idxs, rowSet);
+
+ cnt = idxs.get(0).getRowCount(null);
+ }
+ finally {
+ tbl.unlock(null);
+ }
+
+ // Row count is valid.
+ ResultSet rs = conn.createStatement().executeQuery("select count(*) from t");
+
+ assertTrue(rs.next());
+
+ int cnt2 = rs.getInt(1);
+
+ rs.close();
+
+ assertTrue(cnt2 + " must be >= " + cnt, cnt2 >= cnt);
+ assertTrue(cnt2 <= threads * iterations);
+
+ // Search by ID.
+ rs = conn.createStatement().executeQuery("select * from t where id = '" + id.toString() + "'");
+
+ assertTrue(rs.next());
+ assertFalse(rs.next());
+
+ rs.close();
+
+ // Scan search.
+ if (ps1 == null)
+ ps1 = conn.prepareStatement("select id from t where x = ? order by t desc");
+
+ ps1.setInt(1, x);
+
+ rs = ps1.executeQuery();
+
+ for (;;) {
+ assertTrue(rs.next());
+
+ if (rs.getObject(1).equals(id))
+ break;
+ }
+
+ rs.close();
+ }
+ }
+ return null;
+ }
+ }, threads);
+ }
+
+ /**
+ * Run test in endless loop.
+ *
+ * @param args Arguments.
+ * @throws Exception If failed.
+ */
+ @SuppressWarnings("InfiniteLoopStatement")
+ public static void main(String ... args) throws Exception {
+ for (int i = 0;;) {
+ GridH2TableSelfTest t = new GridH2TableSelfTest();
+
+ t.beforeTest();
+
+ t.testDataLoss();
+
+ t.afterTest();
+
+ System.out.println("..." + ++i);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testRangeQuery() throws Exception {
+ int rows = 3000;
+ int xs = 37;
+
+ long t = System.currentTimeMillis();
+
+ Random rnd = new Random();
+
+ for (int i = 0 ; i < rows; i++) {
+ UUID id = UUID.randomUUID();
+
+ GridH2Row row = row(id, t++, id.toString(), rnd.nextInt(xs));
+
+ assertTrue(tbl.doUpdate(row, false));
+ }
+
+ PreparedStatement ps = conn.prepareStatement("select count(*) from t where x = ?");
+
+ int cnt = 0;
+
+ for (int x = 0; x < xs; x++) {
+ ps.setInt(1, x);
+
+ ResultSet rs = ps.executeQuery();
+
+ assertTrue(rs.next());
+
+ cnt += rs.getInt(1);
+ }
+
+ assertEquals(rows, cnt);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDataLoss() throws Exception {
+ final int threads = 37;
+ final int iterations = 15000;
+
+ final AtomicInteger cntr = new AtomicInteger();
+
+ final UUID[] ids = new UUID[threads * iterations];
+
+ for (int i = 0; i < ids.length; i++)
+ ids[i] = UUID.randomUUID();
+
+ final long t = System.currentTimeMillis();
+
+ final AtomicInteger deleted = new AtomicInteger();
+
+ multithreaded(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ Random rnd = new Random();
+
+ int offset = cntr.getAndIncrement() * iterations;
+
+ synchronized (ids[offset]) {
+ for (int i = 0; i < iterations; i++) {
+ UUID id = ids[offset + i];
+
+ int x = rnd.nextInt(50);
+
+ GridH2Row row = row(id, t, id.toString(), x);
+
+ assertTrue(tbl.doUpdate(row, false));
+ }
+ }
+
+ offset = (offset + iterations) % ids.length;
+
+ synchronized (ids[offset]) {
+ for (int i = 0; i < iterations; i += 2) {
+ UUID id = ids[offset + i];
+
+ int x = rnd.nextInt(50);
+
+ GridH2Row row = row(id, t, id.toString(), x);
+
+ if (tbl.doUpdate(row, true))
+ deleted.incrementAndGet();
+ }
+ }
+
+ return null;
+ }
+ }, threads);
+
+ assertTrue(deleted.get() > 0);
+
+ PreparedStatement p = conn.prepareStatement("select count(*) from t where id = ?");
+
+ for (int i = 1; i < ids.length; i += 2) {
+ p.setObject(1, ids[i]);
+
+ ResultSet rs = p.executeQuery();
+
+ assertTrue(rs.next());
+
+ assertEquals(1, rs.getInt(1));
+ }
+
+ Statement s = conn.createStatement();
+
+ ResultSet rs = s.executeQuery("select count(*) from t");
+
+ assertTrue(rs.next());
+
+ assertEquals(ids.length - deleted.get(), rs.getInt(1));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testRebuildIndexes() throws Exception {
+ ArrayList<GridH2IndexBase> idxsBefore = tbl.indexes();
+
+ assertEquals(3, idxsBefore.size());
+
+ Random rnd = new Random();
+
+ for (int i = 0; i < MAX_X; i++) {
+ UUID id = UUID.randomUUID();
+
+ GridH2Row row = row(id, System.currentTimeMillis(), rnd.nextBoolean() ? id.toString() :
+ UUID.randomUUID().toString(), rnd.nextInt(100));
+
+ tbl.doUpdate(row, false);
+ }
+
+ for (GridH2IndexBase idx : idxsBefore)
+ assertEquals(MAX_X, idx.getRowCountApproximation());
+
+ tbl.rebuildIndexes();
+
+ ArrayList<GridH2IndexBase> idxsAfter = tbl.indexes();
+
+ assertEquals(3, idxsAfter.size());
+
+ for (int i = 0; i < 3; i++) {
+ GridH2IndexBase idxBefore = idxsBefore.get(i);
+ GridH2IndexBase idxAfter = idxsAfter.get(i);
+
+ assertNotSame(idxBefore, idxAfter);
+ assertEquals(idxBefore.getName(), idxAfter.getName());
+ assertSame(idxBefore.getTable(), idxAfter.getTable());
+ assertEquals(idxBefore.getRowCountApproximation(), idxAfter.getRowCountApproximation());
+ assertEquals(idxBefore.getIndexType().isUnique(), idxAfter.getIndexType().isUnique());
+ Assert.assertArrayEquals(idxBefore.getColumns(), idxAfter.getColumns());
+ }
+ }
+
+ /**
+ * Check query plan to correctly select index.
+ *
+ * @param conn Connection.
+ * @param sql Select.
+ * @param search Search token in result.
+ * @throws SQLException If failed.
+ */
+ private void checkQueryPlan(Connection conn, String sql, String search) throws SQLException {
+
+ try (Statement s = conn.createStatement()) {
+ try (ResultSet r = s.executeQuery("EXPLAIN ANALYZE " + sql)) {
+ assertTrue(r.next());
+
+ String plan = r.getString(1);
+
+ assertTrue("Execution plan for '" + sql + "' query should contain '" + search + "'",
+ plan.contains(search));
+ }
+ }
+ }
+
+ /**
+ * @param idxs Indexes.
+ * @param rowSet Rows.
+ * @return Rows.
+ */
+ private Set<Row> checkIndexesConsistent(ArrayList<Index> idxs, @Nullable Set<Row> rowSet) {
+ for (Index idx : idxs) {
+ if (!(idx instanceof GridH2TreeIndex))
+ continue;
+
+ Set<Row> set = new HashSet<>();
+
+ Iterator<GridH2Row> iter = ((GridH2TreeIndex)idx).rows();
+
+ while(iter.hasNext())
+ assertTrue(set.add(iter.next()));
+
+ //((GridH2SnapTreeSet)((GridH2Index)idx).tree).print();
+
+ if (rowSet == null)
+ rowSet = set;
+ else
+ assertEquals(rowSet, set);
+ }
+
+ return rowSet;
+ }
+
+ /**
+ * @param idxs Indexes list.
+ */
+ private void checkOrdered(ArrayList<Index> idxs) {
+ for (Index idx : idxs) {
+ if (!(idx instanceof GridH2TreeIndex))
+ continue;
+
+ GridH2TreeIndex h2Idx = (GridH2TreeIndex)idx;
+
+ checkOrdered(h2Idx, h2Idx);
+ }
+ }
+
+ /**
+ * @param idx Index.
+ * @param cmp Comparator.
+ */
+ private void checkOrdered(GridH2TreeIndex idx, Comparator<? super GridH2Row> cmp) {
+ Iterator<GridH2Row> rows = idx.rows();
+
+ GridH2Row min = null;
+
+ while (rows.hasNext()) {
+ GridH2Row row = rows.next();
+
+ assertNotNull(row);
+
+ assertFalse("Incorrect row order in index: " + idx + "\n min: " + min + "\n row: " + row,
+ min != null && cmp.compare(min, row) > 0);
+
+ min = row;
+ }
+ }
+}
[16/17] incubator-ignite git commit: ignite-qry - spring
Posted by se...@apache.org.
ignite-qry - spring
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/73b5ef6b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/73b5ef6b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/73b5ef6b
Branch: refs/heads/master
Commit: 73b5ef6b040c0a9805d939bef2effba767181c66
Parents: 34115a7
Author: S.Vladykin <sv...@gridgain.com>
Authored: Wed Dec 10 15:17:11 2014 +0300
Committer: S.Vladykin <sv...@gridgain.com>
Committed: Wed Dec 10 15:17:11 2014 +0300
----------------------------------------------------------------------
examples/config/example-cache.xml | 17 +++----
.../clients/src/test/resources/spring-cache.xml | 29 +++--------
.../configuration/IgniteConfiguration.java | 8 +--
.../ignite/spi/indexing/GridIndexingSpi.java | 4 +-
.../grid/cache/query/GridCacheQuery.java | 6 +--
.../cache/query/GridCacheQuerySqlField.java | 2 +-
.../cache/query/GridCacheQuerySqlFunction.java | 4 +-
.../loadtests/colocation/spring-colocation.xml | 13 -----
.../core/src/test/webapp/META-INF/gg-config.xml | 53 ++++++++++++--------
.../processors/query/h2/GridH2Indexing.java | 2 +-
.../test/resources/spring-ping-pong-partner.xml | 21 --------
11 files changed, 60 insertions(+), 99 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/examples/config/example-cache.xml
----------------------------------------------------------------------
diff --git a/examples/config/example-cache.xml b/examples/config/example-cache.xml
index 6e95de4..b3b6877 100644
--- a/examples/config/example-cache.xml
+++ b/examples/config/example-cache.xml
@@ -191,15 +191,6 @@
</property>
</bean>
</property>
-
- <!-- Allow indexing SPI to index primitive values (required for CachePopularNumbersExample). -->
- <property name="indexingSpi">
- <list>
- <bean class="org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi">
- <property name="defaultIndexPrimitiveKey" value="true"/>
- </bean>
- </list>
- </property>
</bean>
<!-- Template for all example cache configurations. -->
@@ -215,5 +206,13 @@
<!-- Set to true to enable indexing for query examples, default value is false. -->
<property name="queryIndexEnabled" value="true"/>
+
+ <!-- Allow to index primitive values. -->
+ <property name="queryConfiguration">
+ <bean class="org.gridgain.grid.cache.query.GridCacheQueryConfiguration">
+ <!-- Index primitives. -->
+ <property name="indexPrimitiveKey" value="true"/>
+ </bean>
+ </property>
</bean>
</beans>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/clients/src/test/resources/spring-cache.xml
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/resources/spring-cache.xml b/modules/clients/src/test/resources/spring-cache.xml
index ba89926..c63e8ec 100644
--- a/modules/clients/src/test/resources/spring-cache.xml
+++ b/modules/clients/src/test/resources/spring-cache.xml
@@ -41,27 +41,6 @@
<!-- Set to local host address just for examples. -->
<property name="localHost" value="127.0.0.1"/>
- <!--
- Allow indexing SPI to index primitive values.
- -->
- <property name="indexingSpi">
- <list>
- <bean class="org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi">
- <!-- Index primitives. -->
- <property name="defaultIndexPrimitiveKey" value="true"/>
-
- <!--
- Set to false to allow different key types for one value type.
-
- Note that this also means that '_key' column cannot participate in
- where clause queries either directly through API, through JDBC driver,
- or through Object Viewer in Visor DevOps Console.
- -->
- <!--property name="defaultIndexFixedTyping" value="false"/-->
- </bean>
- </list>
- </property>
-
<!-- Client configuration. -->
<property name="clientConnectionConfiguration">
<bean class="org.apache.ignite.configuration.ClientConnectionConfiguration"/>
@@ -105,6 +84,14 @@
-->
<property name="queryIndexEnabled" value="true"/>
+ <!-- Allow to index primitive values. -->
+ <property name="queryConfiguration">
+ <bean class="org.gridgain.grid.cache.query.GridCacheQueryConfiguration">
+ <!-- Index primitives. -->
+ <property name="indexPrimitiveKey" value="true"/>
+ </bean>
+ </property>
+
<!--
This shows how to configure number of backups. The below configuration
sets the number of backups to 1 (which is default).
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index b955549..895bdb7 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -2161,13 +2161,9 @@ public class IgniteConfiguration {
}
/**
- * Should return fully configured indexing SPI implementations. If not provided,
- * {@gglink org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi} will be used.
- * <p>
- * Note that user can provide one or multiple instances of this SPI (and select later which one
- * is used in a particular context).
+ * Should return fully configured indexing SPI implementations.
*
- * @return Indexing SPI implementation or <tt>null</tt> to use default implementation.
+ * @return Indexing SPI implementation.
*/
public GridIndexingSpi getIndexingSpi() {
return indexingSpi;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java
index 71cced8..e68d390 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/indexing/GridIndexingSpi.java
@@ -25,7 +25,7 @@ import java.util.*;
* methods. Note again that calling methods from this interface on the obtained instance can lead
* to undefined behavior and explicitly not supported.
*
- * * Here is a Java example on how to configure grid with {@code GridH2IndexingSpi}.
+ * Here is a Java example on how to configure SPI.
* <pre name="code" class="java">
* GridIndexingSpi spi = new MyIndexingSpi();
*
@@ -37,7 +37,7 @@ import java.util.*;
* // Starts grid.
* G.start(cfg);
* </pre>
- * Here is an example of how to configure {@code GridH2IndexingSpi} from Spring XML configuration file.
+ * Here is an example of how to configure SPI from Spring XML configuration file.
* <pre name="code" class="xml">
* <property name="indexingSpi">
* <bean class="com.example.MyIndexingSpi">
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuery.java b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuery.java
index 394c542..a56faf0 100644
--- a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuery.java
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuery.java
@@ -10,6 +10,7 @@
package org.gridgain.grid.cache.query;
import org.apache.ignite.cluster.*;
+import org.apache.ignite.configuration.*;
import org.apache.ignite.lang.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.affinity.*;
@@ -45,7 +46,7 @@ import org.jetbrains.annotations.*;
* <h2 class="header">Custom functions in SQL queries.</h2>
* It is possible to write custom Java methods and call then form SQL queries. These methods must be public static
* and annotated with {@link GridCacheQuerySqlFunction}. Classes containing these methods must be registered in
- * {@gglink org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi#setIndexCustomFunctionClasses(java.lang.Class[])}.
+ * {@link GridQueryConfiguration#setIndexCustomFunctionClasses(Class[])}.
* <h1 class="header">Full Text Queries</h1>
* GridGain supports full text queries based on Apache Lucene engine. This queries are created by
* {@link GridCacheQueries#createFullTextQuery(Class, String)} method. Note that all fields that
@@ -143,8 +144,7 @@ import org.jetbrains.annotations.*;
* mastersQry.execute();
* </pre>
* <h1 class="header">Geo-Spatial Indexes and Queries</h1>
- * GridGain also support <b>Geo-Spatial Indexes</b>. Here is an example of geo-spatial index
- * (supported by {@gglink org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi}):
+ * GridGain also support <b>Geo-Spatial Indexes</b>. Here is an example of geo-spatial index:
* <pre name="code" class="java">
* private class MapPoint implements Serializable {
* // Geospatial index.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlField.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlField.java b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlField.java
index aacdcfe..5846f83 100644
--- a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlField.java
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlField.java
@@ -25,7 +25,7 @@ public @interface GridCacheQuerySqlField {
* Just like with databases, field indexing may require additional overhead
* during updates, but makes select operations faster.
* <p>
- * When {@gglink org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi} is set as indexing SPI and indexed field is
+ * When indexing SPI and indexed field is
* of type {@code com.vividsolutions.jts.geom.Geometry} (or any subclass of this class) then GridGain will
* consider this index as spatial providing performance boost for spatial queries.
*
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlFunction.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlFunction.java b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlFunction.java
index b18bd22..78410bf 100644
--- a/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlFunction.java
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/query/GridCacheQuerySqlFunction.java
@@ -9,12 +9,14 @@
package org.gridgain.grid.cache.query;
+import org.apache.ignite.configuration.*;
+
import java.lang.annotation.*;
/**
* Annotates public static methods in classes to be used in SQL queries as custom functions.
* Annotated class must be registered in H2 indexing SPI using following method
- * {@gglink org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi#setIndexCustomFunctionClasses(java.lang.Class[])}.
+ * {@link GridQueryConfiguration#setIndexCustomFunctionClasses(Class[])}.
* <p>
* Example usage:
* <pre name="code" class="java">
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/core/src/test/java/org/gridgain/loadtests/colocation/spring-colocation.xml
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/gridgain/loadtests/colocation/spring-colocation.xml b/modules/core/src/test/java/org/gridgain/loadtests/colocation/spring-colocation.xml
index 51c7cf7..fc33788 100644
--- a/modules/core/src/test/java/org/gridgain/loadtests/colocation/spring-colocation.xml
+++ b/modules/core/src/test/java/org/gridgain/loadtests/colocation/spring-colocation.xml
@@ -45,19 +45,6 @@
<property name="marshalLocalJobs" value="false"/>
- <!--
- Allow indexing SPI to index primitive values.
- -->
- <property name="indexingSpi">
- <list>
- <bean class="org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi">
- <!-- Index primitives. -->
- <property name="defaultIndexPrimitiveKey" value="false"/>
- <property name="defaultIndexFixedTyping" value="true"/>
- </bean>
- </list>
- </property>
-
<property name="collisionSpi">
<bean class="org.apache.ignite.spi.collision.fifoqueue.FifoQueueCollisionSpi">
<property name="parallelJobsNumber"><util:constant static-field="java.lang.Integer.MAX_VALUE"/></property>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/core/src/test/webapp/META-INF/gg-config.xml
----------------------------------------------------------------------
diff --git a/modules/core/src/test/webapp/META-INF/gg-config.xml b/modules/core/src/test/webapp/META-INF/gg-config.xml
index b0f0af8..1f60c3e 100644
--- a/modules/core/src/test/webapp/META-INF/gg-config.xml
+++ b/modules/core/src/test/webapp/META-INF/gg-config.xml
@@ -72,27 +72,6 @@
<util:constant static-field="org.apache.ignite.events.IgniteEventType.EVTS_CACHE"/>
</property>
- <!--
- Allow indexing SPI to index primitive values.
- -->
- <property name="indexingSpi">
- <list>
- <bean class="org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi">
- <!-- Index primitives. -->
- <property name="defaultIndexPrimitiveKey" value="true"/>
-
- <!--
- Set to false to allow different key types for one value type.
-
- Note that this also means that '_key' column cannot participate in
- where clause queries either directly through API, through JDBC driver,
- or through Object Viewer in Visor DevOps Console.
- -->
- <!--property name="defaultIndexFixedTyping" value="false"/-->
- </bean>
- </list>
- </property>
-
<property name="cacheConfiguration">
<!--
Specify list of cache configurations here. Any property from
@@ -127,6 +106,14 @@
-->
<property name="queryIndexEnabled" value="true"/>
+ <!-- Allow to index primitive values. -->
+ <property name="queryConfiguration">
+ <bean class="org.gridgain.grid.cache.query.GridCacheQueryConfiguration">
+ <!-- Index primitives. -->
+ <property name="indexPrimitiveKey" value="true"/>
+ </bean>
+ </property>
+
<!--
This shows how to configure number of backups. The below configuration
sets the number of backups to 1 (which is default).
@@ -168,6 +155,14 @@
-->
<property name="queryIndexEnabled" value="true"/>
+ <!-- Allow to index primitive values. -->
+ <property name="queryConfiguration">
+ <bean class="org.gridgain.grid.cache.query.GridCacheQueryConfiguration">
+ <!-- Index primitives. -->
+ <property name="indexPrimitiveKey" value="true"/>
+ </bean>
+ </property>
+
<!--
This shows how to configure number of backups. The below configuration
sets the number of backups to 1 (which is default).
@@ -206,6 +201,14 @@
Default value is false.
-->
<property name="queryIndexEnabled" value="true"/>
+
+ <!-- Allow to index primitive values. -->
+ <property name="queryConfiguration">
+ <bean class="org.gridgain.grid.cache.query.GridCacheQueryConfiguration">
+ <!-- Index primitives. -->
+ <property name="indexPrimitiveKey" value="true"/>
+ </bean>
+ </property>
</bean>
<!--
@@ -227,6 +230,14 @@
Default value is false.
-->
<property name="queryIndexEnabled" value="true"/>
+
+ <!-- Allow to index primitive values. -->
+ <property name="queryConfiguration">
+ <bean class="org.gridgain.grid.cache.query.GridCacheQueryConfiguration">
+ <!-- Index primitives. -->
+ <property name="indexPrimitiveKey" value="true"/>
+ </bean>
+ </property>
</bean>
</list>
</property>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java
index 3a850cc..1d7fcdd 100644
--- a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/GridH2Indexing.java
@@ -1928,7 +1928,7 @@ public class GridH2Indexing implements GridQueryIndexing {
catch (ClassCastException e) {
throw new GridException("Failed to convert key to SQL type. " +
"Please make sure that you always store each value type with the same key type or disable " +
- "'defaultIndexFixedTyping' property on GridH2IndexingSpi.", e);
+ "'defaultIndexFixedTyping' property.", e);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/73b5ef6b/modules/scalar/src/test/resources/spring-ping-pong-partner.xml
----------------------------------------------------------------------
diff --git a/modules/scalar/src/test/resources/spring-ping-pong-partner.xml b/modules/scalar/src/test/resources/spring-ping-pong-partner.xml
index 5d4934b..3c9ca5c 100644
--- a/modules/scalar/src/test/resources/spring-ping-pong-partner.xml
+++ b/modules/scalar/src/test/resources/spring-ping-pong-partner.xml
@@ -116,27 +116,6 @@
</property>
</bean>
</property>
-
- <!--
- Allow indexing SPI to index primitive values.
- -->
- <property name="indexingSpi">
- <list>
- <bean class="org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi">
- <!-- Index primitives. -->
- <property name="defaultIndexPrimitiveKey" value="true"/>
-
- <!--
- Set to false to allow different key types for one value type.
-
- Note that this also means that '_key' column cannot participate in
- where clause queries either directly through API, through JDBC driver,
- or through Object Viewer in Visor DevOps Console.
- -->
- <!--property name="defaultIndexFixedTyping" value="false"/-->
- </bean>
- </list>
- </property>
</bean>
</beans>
[09/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryProcessor.java
new file mode 100644
index 0000000..94db08d
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryProcessor.java
@@ -0,0 +1,1672 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+import org.apache.ignite.lang.*;
+import org.apache.ignite.portables.*;
+import org.apache.ignite.spi.indexing.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.kernal.*;
+import org.gridgain.grid.kernal.processors.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.future.*;
+import org.gridgain.grid.util.lang.*;
+import org.gridgain.grid.util.tostring.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.grid.util.worker.*;
+import org.jdk8.backport.*;
+import org.jetbrains.annotations.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import static org.gridgain.grid.kernal.GridComponentType.*;
+import static org.gridgain.grid.kernal.processors.query.GridQueryIndexType.*;
+
+/**
+ * Indexing processor.
+ */
+public class GridQueryProcessor extends GridProcessorAdapter {
+ /** For tests. */
+ public static Class<? extends GridQueryIndexing> idxCls;
+
+ /** */
+ private final GridSpinBusyLock busyLock = new GridSpinBusyLock();
+
+ /** Type descriptors. */
+ private final ConcurrentMap<TypeId, TypeDescriptor> types = new ConcurrentHashMap8<>();
+
+ /** Type descriptors. */
+ private final ConcurrentMap<TypeName, TypeDescriptor> typesByName = new ConcurrentHashMap8<>();
+
+ /** */
+ private ExecutorService execSvc;
+
+ /** */
+ private final GridQueryIndexing idx;
+
+ /** Configuration-declared types. */
+ private final Map<TypeName, GridCacheQueryTypeMetadata> declaredTypesByName = new HashMap<>();
+
+ /** Configuration-declared types. */
+ private Map<TypeId, GridCacheQueryTypeMetadata> declaredTypesById;
+
+ /** Portable IDs. */
+ private Map<Integer, String> portableIds;
+
+ /** Type resolvers per space name. */
+ private Map<String, GridCacheQueryTypeResolver> typeResolvers = new HashMap<>();
+
+ /**
+ * @param ctx Kernal context.
+ */
+ public GridQueryProcessor(GridKernalContext ctx) throws GridException {
+ super(ctx);
+
+ if (idxCls != null) {
+ idx = U.newInstance(idxCls);
+
+ idxCls = null;
+ }
+ else
+ idx = INDEXING.inClassPath() ? U.<GridQueryIndexing>newInstance(INDEXING.className()) : null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws GridException {
+ super.start();
+
+ if (idx != null) {
+ ctx.resource().injectGeneric(idx);
+
+ idx.start(ctx);
+
+ for (GridCacheConfiguration ccfg : ctx.config().getCacheConfiguration()){
+ GridCacheQueryConfiguration qryCfg = ccfg.getQueryConfiguration();
+
+ if (qryCfg != null) {
+ if (!F.isEmpty(qryCfg.getTypeMetadata())) {
+ for (GridCacheQueryTypeMetadata meta : qryCfg.getTypeMetadata())
+ declaredTypesByName.put(new TypeName(ccfg.getName(), meta.getType()), meta);
+ }
+
+ if (qryCfg.getTypeResolver() != null)
+ typeResolvers.put(ccfg.getName(), qryCfg.getTypeResolver());
+ }
+ }
+
+ execSvc = ctx.config().getExecutorService();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onKernalStop(boolean cancel) {
+ super.onKernalStop(cancel);
+
+ busyLock.block();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop(boolean cancel) throws GridException {
+ super.stop(cancel);
+
+ if (idx != null)
+ idx.stop();
+ }
+
+ /**
+ * Returns number of objects of given type for given space of spi.
+ *
+ * @param space Space.
+ * @param valType Value type.
+ * @return Objects number or -1 if this type is unknown for given SPI and space.
+ * @throws GridException If failed.
+ */
+ public long size(@Nullable String space, Class<?> valType) throws GridException {
+ checkEnabled();
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to get space size (grid is stopping).");
+
+ try {
+ TypeDescriptor desc = types.get(new TypeId(space, valType));
+
+ if (desc == null || !desc.registered())
+ return -1;
+
+ return idx.size(space, desc, null);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * Rebuilds all search indexes of given value type for given space of spi.
+ *
+ * @param space Space.
+ * @param valTypeName Value type name.
+ * @return Future that will be completed when rebuilding of all indexes is finished.
+ */
+ public IgniteFuture<?> rebuildIndexes(@Nullable final String space, String valTypeName) {
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to rebuild indexes (grid is stopping).");
+
+ try {
+ return rebuildIndexes(space, typesByName.get(new TypeName(space, valTypeName)));
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * @param space Space.
+ * @param desc Type descriptor.
+ * @return Future that will be completed when rebuilding of all indexes is finished.
+ */
+ private IgniteFuture<?> rebuildIndexes(@Nullable final String space, @Nullable final TypeDescriptor desc) {
+ if (idx == null)
+ return new GridFinishedFuture<>(ctx, new GridException("Indexing is disabled."));
+
+ if (desc == null || !desc.registered())
+ return new GridFinishedFuture<Void>(ctx);
+
+ final GridWorkerFuture<?> fut = new GridWorkerFuture<Void>();
+
+ GridWorker w = new GridWorker(ctx.gridName(), "index-rebuild-worker", log) {
+ @Override protected void body() {
+ try {
+ idx.rebuildIndexes(space, desc);
+
+ fut.onDone();
+ }
+ catch (Exception e) {
+ fut.onDone(e);
+ }
+ catch (Throwable e) {
+ log.error("Failed to rebuild indexes for type: " + desc.name(), e);
+
+ fut.onDone(e);
+ }
+ }
+ };
+
+ fut.setWorker(w);
+
+ execSvc.execute(w);
+
+ return fut;
+ }
+
+ /**
+ * Rebuilds all search indexes for given spi.
+ *
+ * @return Future that will be completed when rebuilding of all indexes is finished.
+ */
+ @SuppressWarnings("unchecked")
+ public IgniteFuture<?> rebuildAllIndexes() {
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to get space size (grid is stopping).");
+
+ try {
+ GridCompoundFuture<?, ?> fut = new GridCompoundFuture<Object, Object>(ctx);
+
+ for (Map.Entry<TypeId, TypeDescriptor> e : types.entrySet())
+ fut.add((IgniteFuture)rebuildIndexes(e.getKey().space, e.getValue()));
+
+ fut.markInitialized();
+
+ return fut;
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * Writes key-value pair to index.
+ *
+ * @param space Space.
+ * @param key Key.
+ * @param keyBytes Byte array with key data.
+ * @param val Value.
+ * @param valBytes Byte array with value data.
+ * @param ver Cache entry version.
+ * @param expirationTime Expiration time or 0 if never expires.
+ * @throws GridException In case of error.
+ */
+ @SuppressWarnings("unchecked")
+ public <K, V> void store(final String space, final K key, @Nullable byte[] keyBytes, final V val,
+ @Nullable byte[] valBytes, byte[] ver, long expirationTime) throws GridException {
+ assert key != null;
+ assert val != null;
+
+ ctx.indexing().store(space, key, val, expirationTime);
+
+ if (idx == null)
+ return;
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to write to index (grid is stopping).");
+
+ try {
+ if (log.isDebugEnabled())
+ log.debug("Storing key to cache query index [key=" + key + ", value=" + val + "]");
+
+ final Class<?> valCls = val.getClass();
+ final Class<?> keyCls = key.getClass();
+
+ TypeId id = null;
+
+ GridCacheQueryTypeResolver rslvr = typeResolvers.get(space);
+
+ if (rslvr != null) {
+ String typeName = rslvr.resolveTypeName(key, val);
+
+ if (typeName != null)
+ id = new TypeId(space, ctx.portable().typeId(typeName));
+ }
+
+ if (id == null) {
+ if (val instanceof PortableObject) {
+ PortableObject portable = (PortableObject)val;
+
+ int typeId = portable.typeId();
+
+ String typeName = portableName(typeId);
+
+ if (typeName == null)
+ return;
+
+ id = new TypeId(space, typeId);
+ }
+ else
+ id = new TypeId(space, valCls);
+ }
+
+ TypeDescriptor desc = types.get(id);
+
+ if (desc == null) {
+ desc = new TypeDescriptor();
+
+ TypeDescriptor existing = types.putIfAbsent(id, desc);
+
+ if (existing != null)
+ desc = existing;
+ }
+
+ if (!desc.succeeded()) {
+ final TypeDescriptor d = desc;
+
+ d.init(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ d.keyClass(keyCls);
+ d.valueClass(valCls);
+
+ if (key instanceof PortableObject) {
+ PortableObject portableKey = (PortableObject)key;
+
+ String typeName = portableName(portableKey.typeId());
+
+ if (typeName != null) {
+ GridCacheQueryTypeMetadata keyMeta = declaredType(space, portableKey.typeId());
+
+ if (keyMeta != null)
+ processPortableMeta(true, keyMeta, d);
+ }
+ }
+ else {
+ GridCacheQueryTypeMetadata keyMeta = declaredType(space, keyCls.getName());
+
+ if (keyMeta == null)
+ processAnnotationsInClass(true, d.keyCls, d, null);
+ else
+ processClassMeta(true, d.keyCls, keyMeta, d);
+ }
+
+ if (val instanceof PortableObject) {
+ PortableObject portableVal = (PortableObject)val;
+
+ String typeName = portableName(portableVal.typeId());
+
+ if (typeName != null) {
+ GridCacheQueryTypeMetadata valMeta = declaredType(space, portableVal.typeId());
+
+ d.name(typeName);
+
+ if (valMeta != null)
+ processPortableMeta(false, valMeta, d);
+ }
+ }
+ else {
+ String valTypeName = typeName(valCls);
+
+ d.name(valTypeName);
+
+ GridCacheQueryTypeMetadata typeMeta = declaredType(space, valCls.getName());
+
+ if (typeMeta == null)
+ processAnnotationsInClass(false, d.valCls, d, null);
+ else
+ processClassMeta(false, d.valCls, typeMeta, d);
+ }
+
+ d.registered(idx.registerType(space, d));
+
+ typesByName.put(new TypeName(space, d.name()), d);
+
+ return null;
+ }
+ });
+ }
+
+ if (!desc.registered())
+ return;
+
+ if (!desc.valueClass().equals(valCls))
+ throw new GridException("Failed to update index due to class name conflict" +
+ "(multiple classes with same simple name are stored in the same cache) " +
+ "[expCls=" + desc.valueClass().getName() + ", actualCls=" + valCls.getName() + ']');
+
+ idx.store(space, desc, key, val, ver, expirationTime);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * @throws GridException If failed.
+ */
+ private void checkEnabled() throws GridException {
+ if (idx == null)
+ throw new GridException("Indexing is disabled.");
+ }
+
+ /**
+ * @param space Space.
+ * @param clause Clause.
+ * @param params Parameters collection.
+ * @param resType Result type.
+ * @param filters Filters.
+ * @return Key/value rows.
+ * @throws GridException If failed.
+ */
+ @SuppressWarnings("unchecked")
+ public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> query(String space, String clause,
+ Collection<Object> params, String resType, GridIndexingQueryFilter filters)
+ throws GridException {
+ checkEnabled();
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to execute query (grid is stopping).");
+
+ try {
+ TypeDescriptor type = typesByName.get(new TypeName(space, resType));
+
+ if (type == null || !type.registered())
+ return new GridEmptyCloseableIterator<>();
+
+ return idx.query(space, clause, params, type, filters);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * @param space Space.
+ * @param key Key.
+ * @throws GridException Thrown in case of any errors.
+ */
+ @SuppressWarnings("unchecked")
+ public void remove(String space, Object key) throws GridException {
+ assert key != null;
+
+ ctx.indexing().remove(space, key);
+
+ if (idx == null)
+ return;
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to remove from index (grid is stopping).");
+
+ try {
+ idx.remove(space, key);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * Gets type name by class.
+ *
+ * @param cls Class.
+ * @return Type name.
+ */
+ public String typeName(Class<?> cls) {
+ String typeName = cls.getSimpleName();
+
+ // To protect from failure on anonymous classes.
+ if (F.isEmpty(typeName)) {
+ String pkg = cls.getPackage().getName();
+
+ typeName = cls.getName().substring(pkg.length() + (pkg.isEmpty() ? 0 : 1));
+ }
+
+ if (cls.isArray()) {
+ assert typeName.endsWith("[]");
+
+ typeName = typeName.substring(0, typeName.length() - 2) + "_array";
+ }
+
+ return typeName;
+ }
+
+ /**
+ * Gets portable type name by portable ID.
+ *
+ * @param typeId Type ID.
+ * @return Name.
+ */
+ private String portableName(int typeId) {
+ Map<Integer, String> portableIds = this.portableIds;
+
+ if (portableIds == null) {
+ portableIds = new HashMap<>();
+
+ for (GridCacheConfiguration ccfg : ctx.config().getCacheConfiguration()){
+ GridCacheQueryConfiguration qryCfg = ccfg.getQueryConfiguration();
+
+ if (qryCfg != null) {
+ for (GridCacheQueryTypeMetadata meta : qryCfg.getTypeMetadata())
+ portableIds.put(ctx.portable().typeId(meta.getType()), meta.getType());
+ }
+ }
+
+ this.portableIds = portableIds;
+ }
+
+ return portableIds.get(typeId);
+ }
+
+ /**
+ * @param space Space name.
+ * @param typeId Type ID.
+ * @return Type meta data if it was declared in configuration.
+ */
+ @Nullable private GridCacheQueryTypeMetadata declaredType(String space, int typeId) {
+ Map<TypeId, GridCacheQueryTypeMetadata> declaredTypesById = this.declaredTypesById;
+
+ if (declaredTypesById == null) {
+ declaredTypesById = new HashMap<>();
+
+ for (GridCacheConfiguration ccfg : ctx.config().getCacheConfiguration()){
+ GridCacheQueryConfiguration qryCfg = ccfg.getQueryConfiguration();
+
+ if (qryCfg != null) {
+ for (GridCacheQueryTypeMetadata meta : qryCfg.getTypeMetadata())
+ declaredTypesById.put(new TypeId(ccfg.getName(), ctx.portable().typeId(meta.getType())), meta);
+ }
+ }
+
+ this.declaredTypesById = declaredTypesById;
+ }
+
+ return declaredTypesById.get(new TypeId(space, typeId));
+ }
+
+ /**
+ * @param space Space name.
+ * @param typeName Type name.
+ * @return Type meta data if it was declared in configuration.
+ */
+ @Nullable private GridCacheQueryTypeMetadata declaredType(String space, String typeName) {
+ return declaredTypesByName.get(new TypeName(space, typeName));
+ }
+
+ /**
+ * @param space Space.
+ * @param clause Clause.
+ * @param resType Result type.
+ * @param filters Key and value filters.
+ * @param <K> Key type.
+ * @param <V> Value type.
+ * @return Key/value rows.
+ * @throws GridException If failed.
+ */
+ @SuppressWarnings("unchecked")
+ public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryText(String space, String clause, String resType,
+ GridIndexingQueryFilter filters) throws GridException {
+ checkEnabled();
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to execute query (grid is stopping).");
+
+ try {
+ TypeDescriptor type = typesByName.get(new TypeName(space, resType));
+
+ if (type == null || !type.registered())
+ return new GridEmptyCloseableIterator<>();
+
+ return idx.queryText(space, clause, type, filters);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * @param space Space name.
+ * @param clause Clause.
+ * @param params Parameters collection.
+ * @param filters Key and value filters.
+ * @return Field rows.
+ * @throws GridException If failed.
+ */
+ public <K, V> GridQueryFieldsResult queryFields(@Nullable String space, String clause, Collection<Object> params,
+ GridIndexingQueryFilter filters) throws GridException {
+ checkEnabled();
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to execute query (grid is stopping).");
+
+ try {
+ return idx.queryFields(space, clause, params, filters);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * Will be called when entry for key will be swapped.
+ *
+ * @param spaceName Space name.
+ * @param key key.
+ * @throws GridException If failed.
+ */
+ public void onSwap(String spaceName, Object key) throws GridException {
+ ctx.indexing().onSwap(spaceName, key);
+
+ if (idx == null)
+ return;
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to process swap event (grid is stopping).");
+
+ try {
+ idx.onSwap(spaceName, key);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * Will be called when entry for key will be unswapped.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @param val Value.
+ * @param valBytes Value bytes.
+ * @throws GridException If failed.
+ */
+ public void onUnswap(String spaceName, Object key, Object val, byte[] valBytes)
+ throws GridException {
+ ctx.indexing().onUnswap(spaceName, key, val);
+
+ if (idx == null)
+ return;
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to process swap event (grid is stopping).");
+
+ try {
+ idx.onUnswap(spaceName, key, val, valBytes);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * Removes index tables for all classes belonging to given class loader.
+ *
+ * @param space Space name.
+ * @param ldr Class loader to undeploy.
+ * @throws GridException If undeploy failed.
+ */
+ public void onUndeploy(@Nullable String space, ClassLoader ldr) throws GridException {
+ if (idx == null)
+ return;
+
+ if (!busyLock.enterBusy())
+ throw new IllegalStateException("Failed to process undeploy event (grid is stopping).");
+
+ try {
+ Iterator<Map.Entry<TypeId, TypeDescriptor>> it = types.entrySet().iterator();
+
+ while (it.hasNext()) {
+ Map.Entry<TypeId, TypeDescriptor> e = it.next();
+
+ if (!F.eq(e.getKey().space, space))
+ continue;
+
+ TypeDescriptor desc = e.getValue();
+
+ if (ldr.equals(U.detectClassLoader(desc.valCls)) || ldr.equals(U.detectClassLoader(desc.keyCls))) {
+ idx.unregisterType(e.getKey().space, desc);
+
+ it.remove();
+ }
+ }
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * Process annotations for class.
+ *
+ * @param key If given class relates to key.
+ * @param cls Class.
+ * @param type Type descriptor.
+ * @param parent Parent in case of embeddable.
+ * @throws GridException In case of error.
+ */
+ static void processAnnotationsInClass(boolean key, Class<?> cls, TypeDescriptor type,
+ @Nullable ClassProperty parent) throws GridException {
+ if (U.isJdk(cls))
+ return;
+
+ if (parent != null && parent.knowsClass(cls))
+ throw new GridException("Recursive reference found in type: " + cls.getName());
+
+ if (parent == null) { // Check class annotation at top level only.
+ GridCacheQueryTextField txtAnnCls = cls.getAnnotation(GridCacheQueryTextField.class);
+
+ if (txtAnnCls != null)
+ type.valueTextIndex(true);
+
+ GridCacheQueryGroupIndex grpIdx = cls.getAnnotation(GridCacheQueryGroupIndex.class);
+
+ if (grpIdx != null)
+ type.addIndex(grpIdx.name(), SORTED);
+
+ GridCacheQueryGroupIndex.List grpIdxList = cls.getAnnotation(GridCacheQueryGroupIndex.List.class);
+
+ if (grpIdxList != null && !F.isEmpty(grpIdxList.value())) {
+ for (GridCacheQueryGroupIndex idx : grpIdxList.value())
+ type.addIndex(idx.name(), SORTED);
+ }
+ }
+
+ for (Class<?> c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) {
+ for (Field field : c.getDeclaredFields()) {
+ GridCacheQuerySqlField sqlAnn = field.getAnnotation(GridCacheQuerySqlField.class);
+ GridCacheQueryTextField txtAnn = field.getAnnotation(GridCacheQueryTextField.class);
+
+ if (sqlAnn != null || txtAnn != null) {
+ ClassProperty prop = new ClassProperty(field);
+
+ prop.parent(parent);
+
+ processAnnotation(key, sqlAnn, txtAnn, field.getType(), prop, type);
+
+ type.addProperty(key, prop, true);
+ }
+ }
+
+ for (Method mtd : c.getDeclaredMethods()) {
+ GridCacheQuerySqlField sqlAnn = mtd.getAnnotation(GridCacheQuerySqlField.class);
+ GridCacheQueryTextField txtAnn = mtd.getAnnotation(GridCacheQueryTextField.class);
+
+ if (sqlAnn != null || txtAnn != null) {
+ if (mtd.getParameterTypes().length != 0)
+ throw new GridException("Getter with GridCacheQuerySqlField " +
+ "annotation cannot have parameters: " + mtd);
+
+ ClassProperty prop = new ClassProperty(mtd);
+
+ prop.parent(parent);
+
+ processAnnotation(key, sqlAnn, txtAnn, mtd.getReturnType(), prop, type);
+
+ type.addProperty(key, prop, true);
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes annotation at field or method.
+ *
+ * @param key If given class relates to key.
+ * @param sqlAnn SQL annotation, can be {@code null}.
+ * @param txtAnn H2 text annotation, can be {@code null}.
+ * @param cls Class of field or return type for method.
+ * @param prop Current property.
+ * @param desc Class description.
+ * @throws GridException In case of error.
+ */
+ static void processAnnotation(boolean key, GridCacheQuerySqlField sqlAnn, GridCacheQueryTextField txtAnn,
+ Class<?> cls, ClassProperty prop, TypeDescriptor desc) throws GridException {
+ if (sqlAnn != null) {
+ processAnnotationsInClass(key, cls, desc, prop);
+
+ if (!sqlAnn.name().isEmpty())
+ prop.name(sqlAnn.name());
+
+ if (sqlAnn.index() || sqlAnn.unique()) {
+ String idxName = prop.name() + "_idx";
+
+ desc.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
+
+ desc.addFieldToIndex(idxName, prop.name(), 0, sqlAnn.descending());
+ }
+
+ if (!F.isEmpty(sqlAnn.groups())) {
+ for (String group : sqlAnn.groups())
+ desc.addFieldToIndex(group, prop.name(), 0, false);
+ }
+
+ if (!F.isEmpty(sqlAnn.orderedGroups())) {
+ for (GridCacheQuerySqlField.Group idx : sqlAnn.orderedGroups())
+ desc.addFieldToIndex(idx.name(), prop.name(), idx.order(), idx.descending());
+ }
+ }
+
+ if (txtAnn != null)
+ desc.addFieldToTextIndex(prop.name());
+ }
+
+ /**
+ * Processes declarative metadata for class.
+ *
+ * @param key Key or value flag.
+ * @param cls Class to process.
+ * @param meta Type metadata.
+ * @param d Type descriptor.
+ * @throws GridException If failed.
+ */
+ static void processClassMeta(boolean key, Class<?> cls, GridCacheQueryTypeMetadata meta, TypeDescriptor d)
+ throws GridException {
+ for (Map.Entry<String, Class<?>> entry : meta.getAscendingFields().entrySet()) {
+ ClassProperty prop = buildClassProperty(cls, entry.getKey(), entry.getValue());
+
+ d.addProperty(key, prop, false);
+
+ String idxName = prop.name() + "_idx";
+
+ d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
+
+ d.addFieldToIndex(idxName, prop.name(), 0, false);
+ }
+
+ for (Map.Entry<String, Class<?>> entry : meta.getDescendingFields().entrySet()) {
+ ClassProperty prop = buildClassProperty(cls, entry.getKey(), entry.getValue());
+
+ d.addProperty(key, prop, false);
+
+ String idxName = prop.name() + "_idx";
+
+ d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
+
+ d.addFieldToIndex(idxName, prop.name(), 0, true);
+ }
+
+ for (String txtIdx : meta.getTextFields()) {
+ ClassProperty prop = buildClassProperty(cls, txtIdx, String.class);
+
+ d.addProperty(key, prop, false);
+
+ d.addFieldToTextIndex(prop.name());
+ }
+
+ Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps = meta.getGroups();
+
+ if (grps != null) {
+ for (Map.Entry<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> entry : grps.entrySet()) {
+ String idxName = entry.getKey();
+
+ LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> idxFields = entry.getValue();
+
+ int order = 0;
+
+ for (Map.Entry<String, IgniteBiTuple<Class<?>, Boolean>> idxField : idxFields.entrySet()) {
+ ClassProperty prop = buildClassProperty(cls, idxField.getKey(), idxField.getValue().get1());
+
+ d.addProperty(key, prop, false);
+
+ Boolean descending = idxField.getValue().get2();
+
+ d.addFieldToIndex(idxName, prop.name(), order, descending != null && descending);
+
+ order++;
+ }
+ }
+ }
+
+ for (Map.Entry<String, Class<?>> entry : meta.getQueryFields().entrySet()) {
+ ClassProperty prop = buildClassProperty(cls, entry.getKey(), entry.getValue());
+
+ d.addProperty(key, prop, false);
+ }
+ }
+
+ /**
+ * Processes declarative metadata for portable object.
+ *
+ * @param key Key or value flag.
+ * @param meta Declared metadata.
+ * @param d Type descriptor.
+ * @throws GridException If failed.
+ */
+ static void processPortableMeta(boolean key, GridCacheQueryTypeMetadata meta, TypeDescriptor d)
+ throws GridException {
+ for (Map.Entry<String, Class<?>> entry : meta.getAscendingFields().entrySet()) {
+ PortableProperty prop = buildPortableProperty(entry.getKey(), entry.getValue());
+
+ d.addProperty(key, prop, false);
+
+ String idxName = prop.name() + "_idx";
+
+ d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
+
+ d.addFieldToIndex(idxName, prop.name(), 0, false);
+ }
+
+ for (Map.Entry<String, Class<?>> entry : meta.getDescendingFields().entrySet()) {
+ PortableProperty prop = buildPortableProperty(entry.getKey(), entry.getValue());
+
+ d.addProperty(key, prop, false);
+
+ String idxName = prop.name() + "_idx";
+
+ d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
+
+ d.addFieldToIndex(idxName, prop.name(), 0, true);
+ }
+
+ for (String txtIdx : meta.getTextFields()) {
+ PortableProperty prop = buildPortableProperty(txtIdx, String.class);
+
+ d.addProperty(key, prop, false);
+
+ d.addFieldToTextIndex(prop.name());
+ }
+
+ Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps = meta.getGroups();
+
+ if (grps != null) {
+ for (Map.Entry<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> entry : grps.entrySet()) {
+ String idxName = entry.getKey();
+
+ LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> idxFields = entry.getValue();
+
+ int order = 0;
+
+ for (Map.Entry<String, IgniteBiTuple<Class<?>, Boolean>> idxField : idxFields.entrySet()) {
+ PortableProperty prop = buildPortableProperty(idxField.getKey(), idxField.getValue().get1());
+
+ d.addProperty(key, prop, false);
+
+ Boolean descending = idxField.getValue().get2();
+
+ d.addFieldToIndex(idxName, prop.name(), order, descending != null && descending);
+
+ order++;
+ }
+ }
+ }
+
+ for (Map.Entry<String, Class<?>> entry : meta.getQueryFields().entrySet()) {
+ PortableProperty prop = buildPortableProperty(entry.getKey(), entry.getValue());
+
+ if (!d.props.containsKey(prop.name()))
+ d.addProperty(key, prop, false);
+ }
+ }
+
+ /**
+ * Builds portable object property.
+ *
+ * @param pathStr String representing path to the property. May contains dots '.' to identify
+ * nested fields.
+ * @param resType Result type.
+ * @return Portable property.
+ */
+ static PortableProperty buildPortableProperty(String pathStr, Class<?> resType) {
+ String[] path = pathStr.split("\\.");
+
+ PortableProperty res = null;
+
+ for (String prop : path)
+ res = new PortableProperty(prop, res, resType);
+
+ return res;
+ }
+
+ /**
+ * @param cls Source type class.
+ * @param pathStr String representing path to the property. May contains dots '.' to identify nested fields.
+ * @param resType Expected result type.
+ * @return Property instance corresponding to the given path.
+ * @throws GridException If property cannot be created.
+ */
+ static ClassProperty buildClassProperty(Class<?> cls, String pathStr, Class<?> resType) throws GridException {
+ String[] path = pathStr.split("\\.");
+
+ ClassProperty res = null;
+
+ for (String prop : path) {
+ ClassProperty tmp;
+
+ try {
+ StringBuilder bld = new StringBuilder("get");
+
+ bld.append(prop);
+
+ bld.setCharAt(3, Character.toUpperCase(bld.charAt(3)));
+
+ tmp = new ClassProperty(cls.getMethod(bld.toString()));
+ }
+ catch (NoSuchMethodException ignore) {
+ try {
+ tmp = new ClassProperty(cls.getDeclaredField(prop));
+ }
+ catch (NoSuchFieldException ignored) {
+ throw new GridException("Failed to find getter method or field for property named " +
+ "'" + prop + "': " + cls.getName());
+ }
+ }
+
+ tmp.parent(res);
+
+ cls = tmp.type();
+
+ res = tmp;
+ }
+
+ if (!U.box(resType).isAssignableFrom(U.box(res.type())))
+ throw new GridException("Failed to create property for given path (actual property type is not assignable" +
+ " to declared type [path=" + pathStr + ", actualType=" + res.type().getName() +
+ ", declaredType=" + resType.getName() + ']');
+
+ return res;
+ }
+
+ /**
+ * Gets types for space.
+ *
+ * @param space Space name.
+ * @return Descriptors.
+ */
+ public Collection<GridQueryTypeDescriptor> types(@Nullable String space) {
+ Collection<GridQueryTypeDescriptor> spaceTypes = new ArrayList<>(
+ Math.min(10, types.size()));
+
+ for (Map.Entry<TypeId, TypeDescriptor> e : types.entrySet()) {
+ TypeDescriptor desc = e.getValue();
+
+ if (desc.registered() && F.eq(e.getKey().space, space))
+ spaceTypes.add(desc);
+ }
+
+ return spaceTypes;
+ }
+
+ /**
+ * Gets type for space and type name.
+ *
+ * @param space Space name.
+ * @param typeName Type name.
+ * @return Type.
+ * @throws GridException If failed.
+ */
+ public GridQueryTypeDescriptor type(@Nullable String space, String typeName) throws GridException {
+ TypeDescriptor type = typesByName.get(new TypeName(space, typeName));
+
+ if (type == null || !type.registered())
+ throw new GridException("Failed to find type descriptor for type name: " + typeName);
+
+ return type;
+ }
+
+ /**
+ * @param cls Field type.
+ * @return {@code True} if given type is a spatial geometry type based on {@code com.vividsolutions.jts} library.
+ * @throws GridException If failed.
+ */
+ private static boolean isGeometryClass(Class<?> cls) throws GridException { // TODO optimize
+ Class<?> dataTypeCls;
+
+ try {
+ dataTypeCls = Class.forName("org.h2.value.DataType");
+ }
+ catch (ClassNotFoundException ignored) {
+ return false; // H2 is not in classpath.
+ }
+
+ try {
+ Method method = dataTypeCls.getMethod("isGeometryClass", Class.class);
+
+ return (Boolean)method.invoke(null, cls);
+ }
+ catch (Exception e) {
+ throw new GridException("Failed to invoke 'org.h2.value.DataType.isGeometryClass' method.", e);
+ }
+ }
+
+ /**
+ *
+ */
+ private abstract static class Property {
+ /**
+ * Gets this property value from the given object.
+ *
+ * @param x Object with this property.
+ * @return Property value.
+ * @throws GridException If failed.
+ */
+ public abstract Object value(Object x) throws GridException;
+
+ /**
+ * @return Property name.
+ */
+ public abstract String name();
+
+ /**
+ * @return Class member type.
+ */
+ public abstract Class<?> type();
+ }
+
+ /**
+ * Description of type property.
+ */
+ private static class ClassProperty extends Property {
+ /** */
+ private final Member member;
+
+ /** */
+ private ClassProperty parent;
+
+ /** */
+ private String name;
+
+ /** */
+ private boolean field;
+
+ /**
+ * Constructor.
+ *
+ * @param member Element.
+ */
+ ClassProperty(Member member) {
+ this.member = member;
+
+ name = member instanceof Method && member.getName().startsWith("get") && member.getName().length() > 3 ?
+ member.getName().substring(3) : member.getName();
+
+ ((AccessibleObject) member).setAccessible(true);
+
+ field = member instanceof Field;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Object value(Object x) throws GridException {
+ if (parent != null)
+ x = parent.value(x);
+
+ if (x == null)
+ return null;
+
+ try {
+ if (field) {
+ Field field = (Field)member;
+
+ return field.get(x);
+ }
+ else {
+ Method mtd = (Method)member;
+
+ return mtd.invoke(x);
+ }
+ }
+ catch (Exception e) {
+ throw new GridException(e);
+ }
+ }
+
+ /**
+ * @param name Property name.
+ */
+ public void name(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String name() {
+ return name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Class<?> type() {
+ return member instanceof Field ? ((Field)member).getType() : ((Method)member).getReturnType();
+ }
+
+ /**
+ * @param parent Parent property if this is embeddable element.
+ */
+ public void parent(ClassProperty parent) {
+ this.parent = parent;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(ClassProperty.class, this);
+ }
+
+ /**
+ * @param cls Class.
+ * @return {@code true} If this property or some parent relates to member of the given class.
+ */
+ public boolean knowsClass(Class<?> cls) {
+ return member.getDeclaringClass() == cls || (parent != null && parent.knowsClass(cls));
+ }
+ }
+
+ /**
+ *
+ */
+ private static class PortableProperty extends Property {
+ /** Property name. */
+ private String propName;
+
+ /** Parent property. */
+ private PortableProperty parent;
+
+ /** Result class. */
+ private Class<?> type;
+
+ /**
+ * Constructor.
+ *
+ * @param propName Property name.
+ * @param parent Parent property.
+ * @param type Result type.
+ */
+ private PortableProperty(String propName, PortableProperty parent, Class<?> type) {
+ this.propName = propName;
+ this.parent = parent;
+ this.type = type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Object value(Object obj) throws GridException {
+ if (parent != null)
+ obj = parent.value(obj);
+
+ if (obj == null)
+ return null;
+
+ if (!(obj instanceof PortableObject))
+ throw new GridException("Non-portable object received as a result of property extraction " +
+ "[parent=" + parent + ", propName=" + propName + ", obj=" + obj + ']');
+
+ return ((PortableObject)obj).field(propName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String name() {
+ return propName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Class<?> type() {
+ return type;
+ }
+ }
+
+ /**
+ * Descriptor of type.
+ */
+ private static class TypeDescriptor implements GridQueryTypeDescriptor {
+ /** */
+ private String name;
+
+ /** Value field names and types with preserved order. */
+ @GridToStringInclude
+ private final Map<String, Class<?>> valFields = new LinkedHashMap<>();
+
+ /** */
+ @GridToStringExclude
+ private final Map<String, Property> props = new HashMap<>();
+
+ /** Key field names and types with preserved order. */
+ @GridToStringInclude
+ private final Map<String, Class<?>> keyFields = new LinkedHashMap<>();
+
+ /** */
+ @GridToStringInclude
+ private final Map<String, IndexDescriptor> indexes = new HashMap<>();
+
+ /** */
+ private IndexDescriptor fullTextIdx;
+
+ /** */
+ private Class<?> keyCls;
+
+ /** */
+ private Class<?> valCls;
+
+ /** */
+ private boolean valTextIdx;
+
+ /** To ensure that type was registered in SPI and only once. */
+ private final GridAtomicInitializer<Void> initializer = new GridAtomicInitializer<>();
+
+ /** SPI can decide not to register this type. */
+ private boolean registered;
+
+ /**
+ * @param c Initialization callable.
+ * @throws GridException In case of error.
+ */
+ void init(Callable<Void> c) throws GridException {
+ initializer.init(c);
+ }
+
+ /**
+ * @return Waits for initialization.
+ * @throws GridInterruptedException If thread is interrupted.
+ */
+ boolean await() throws GridInterruptedException {
+ return initializer.await();
+ }
+
+ /**
+ * @return Whether initialization was successfully completed.
+ */
+ boolean succeeded() {
+ return initializer.succeeded();
+ }
+
+ /**
+ * @return {@code True} if type registration in SPI was finished and type was not rejected.
+ */
+ boolean registered() {
+ return initializer.succeeded() && registered;
+ }
+
+ /**
+ * @param registered Sets registered flag.
+ */
+ void registered(boolean registered) {
+ this.registered = registered;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String name() {
+ return name;
+ }
+
+ /**
+ * Sets type name.
+ *
+ * @param name Name.
+ */
+ void name(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Map<String, Class<?>> valueFields() {
+ return valFields;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Map<String, Class<?>> keyFields() {
+ return keyFields;
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> T value(Object obj, String field) throws GridException {
+ assert obj != null;
+ assert field != null;
+
+ Property prop = props.get(field);
+
+ if (prop == null)
+ throw new GridException("Failed to find field '" + field + "' in type '" + name + "'.");
+
+ return (T)prop.value(obj);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Map<String, GridQueryIndexDescriptor> indexes() {
+ return Collections.<String, GridQueryIndexDescriptor>unmodifiableMap(indexes);
+ }
+
+ /**
+ * Adds index.
+ *
+ * @param idxName Index name.
+ * @param type Index type.
+ * @return Index descriptor.
+ * @throws GridException In case of error.
+ */
+ public IndexDescriptor addIndex(String idxName, GridQueryIndexType type) throws GridException {
+ IndexDescriptor idx = new IndexDescriptor(type);
+
+ if (indexes.put(idxName, idx) != null)
+ throw new GridException("Index with name '" + idxName + "' already exists.");
+
+ return idx;
+ }
+
+ /**
+ * Adds field to index.
+ *
+ * @param idxName Index name.
+ * @param field Field name.
+ * @param orderNum Fields order number in index.
+ * @param descending Sorting order.
+ * @throws GridException If failed.
+ */
+ public void addFieldToIndex(String idxName, String field, int orderNum,
+ boolean descending) throws GridException {
+ IndexDescriptor desc = indexes.get(idxName);
+
+ if (desc == null)
+ desc = addIndex(idxName, SORTED);
+
+ desc.addField(field, orderNum, descending);
+ }
+
+ /**
+ * Adds field to text index.
+ *
+ * @param field Field name.
+ */
+ public void addFieldToTextIndex(String field) {
+ if (fullTextIdx == null) {
+ fullTextIdx = new IndexDescriptor(FULLTEXT);
+
+ indexes.put(null, fullTextIdx);
+ }
+
+ fullTextIdx.addField(field, 0, false);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Class<?> valueClass() {
+ return valCls;
+ }
+
+ /**
+ * Sets value class.
+ *
+ * @param valCls Value class.
+ */
+ void valueClass(Class<?> valCls) {
+ this.valCls = valCls;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Class<?> keyClass() {
+ return keyCls;
+ }
+
+ /**
+ * Set key class.
+ *
+ * @param keyCls Key class.
+ */
+ void keyClass(Class<?> keyCls) {
+ this.keyCls = keyCls;
+ }
+
+ /**
+ * Adds property to the type descriptor.
+ *
+ * @param key If given property relates to key.
+ * @param prop Property.
+ * @param failOnDuplicate Fail on duplicate flag.
+ * @throws GridException In case of error.
+ */
+ public void addProperty(boolean key, Property prop, boolean failOnDuplicate) throws GridException {
+ String name = prop.name();
+
+ if (props.put(name, prop) != null && failOnDuplicate)
+ throw new GridException("Property with name '" + name + "' already exists.");
+
+ if (key)
+ keyFields.put(name, prop.type());
+ else
+ valFields.put(name, prop.type());
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean valueTextIndex() {
+ return valTextIdx;
+ }
+
+ /**
+ * Sets if this value should be text indexed.
+ *
+ * @param valTextIdx Flag value.
+ */
+ public void valueTextIndex(boolean valTextIdx) {
+ this.valTextIdx = valTextIdx;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TypeDescriptor.class, this);
+ }
+ }
+
+ /**
+ * Index descriptor.
+ */
+ private static class IndexDescriptor implements GridQueryIndexDescriptor {
+ /** Fields sorted by order number. */
+ private final Collection<T2<String, Integer>> fields = new TreeSet<>(
+ new Comparator<T2<String, Integer>>() {
+ @Override public int compare(T2<String, Integer> o1, T2<String, Integer> o2) {
+ if (o1.get2().equals(o2.get2())) // Order is equal, compare field names to avoid replace in Set.
+ return o1.get1().compareTo(o2.get1());
+
+ return o1.get2() < o2.get2() ? -1 : 1;
+ }
+ });
+
+ /** Fields which should be indexed in descending order. */
+ private Collection<String> descendings;
+
+ /** */
+ private final GridQueryIndexType type;
+
+ /**
+ * @param type Type.
+ */
+ private IndexDescriptor(GridQueryIndexType type) {
+ assert type != null;
+
+ this.type = type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Collection<String> fields() {
+ Collection<String> res = new ArrayList<>(fields.size());
+
+ for (T2<String, Integer> t : fields)
+ res.add(t.get1());
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean descending(String field) {
+ return descendings != null && descendings.contains(field);
+ }
+
+ /**
+ * Adds field to this index.
+ *
+ * @param field Field name.
+ * @param orderNum Field order number in this index.
+ * @param descending Sort order.
+ */
+ public void addField(String field, int orderNum, boolean descending) {
+ fields.add(new T2<>(field, orderNum));
+
+ if (descending) {
+ if (descendings == null)
+ descendings = new HashSet<>();
+
+ descendings.add(field);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridQueryIndexType type() {
+ return type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(IndexDescriptor.class, this);
+ }
+ }
+
+ /**
+ * Identifying TypeDescriptor by space and value class.
+ */
+ private static class TypeId {
+ /** */
+ private final String space;
+
+ /** Value type. */
+ private final Class<?> valType;
+
+ /** Value type ID. */
+ private final int valTypeId;
+
+ /**
+ * Constructor.
+ *
+ * @param space Space name.
+ * @param valType Value type.
+ */
+ private TypeId(String space, Class<?> valType) {
+ assert valType != null;
+
+ this.space = space;
+ this.valType = valType;
+
+ valTypeId = 0;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param space Space name.
+ * @param valTypeId Value type ID.
+ */
+ private TypeId(String space, int valTypeId) {
+ this.space = space;
+ this.valTypeId = valTypeId;
+
+ valType = null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TypeId typeId = (TypeId)o;
+
+ return (valTypeId == typeId.valTypeId) &&
+ (valType != null ? valType == typeId.valType : typeId.valType == null) &&
+ (space != null ? space.equals(typeId.space) : typeId.space == null);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return 31 * (space != null ? space.hashCode() : 0) + (valType != null ? valType.hashCode() : valTypeId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TypeId.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class TypeName {
+ /** */
+ private final String space;
+
+ /** */
+ private final String typeName;
+
+ /**
+ * @param space Space name.
+ * @param typeName Type name.
+ */
+ private TypeName(@Nullable String space, String typeName) {
+ assert !F.isEmpty(typeName) : typeName;
+
+ this.space = space;
+ this.typeName = typeName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TypeName other = (TypeName)o;
+
+ return (space != null ? space.equals(other.space) : other.space == null) &&
+ typeName.equals(other.typeName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return 31 * (space != null ? space.hashCode() : 0) + typeName.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TypeName.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryTypeDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryTypeDescriptor.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryTypeDescriptor.java
new file mode 100644
index 0000000..d835349
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryTypeDescriptor.java
@@ -0,0 +1,79 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+
+import org.gridgain.grid.*;
+
+import java.util.*;
+
+/**
+ * Value descriptor which allows to extract fields from value object of given type.
+ */
+public interface GridQueryTypeDescriptor {
+ /**
+ * Gets type name which uniquely identifies this type.
+ *
+ * @return Type name which uniquely identifies this type.
+ */
+ public String name();
+
+ /**
+ * Gets mapping from values field name to its type.
+ *
+ * @return Fields that can be indexed, participate in queries and can be queried using method.
+ */
+ public Map<String, Class<?>> valueFields();
+
+ /**
+ * Gets mapping from keys field name to its type.
+ *
+ * @return Fields that can be indexed, participate in queries and can be queried.
+ */
+ public Map<String, Class<?>> keyFields();
+
+ /**
+ * Gets field value for given object.
+ *
+ * @param obj Object to get field value from.
+ * @param field Field name.
+ * @return Value for given field.
+ * @throws GridException If failed.
+ */
+ public <T> T value(Object obj, String field) throws GridException;
+
+ /**
+ * Gets indexes for this type.
+ *
+ * @return Indexes for this type.
+ */
+ public Map<String, GridQueryIndexDescriptor> indexes();
+
+ /**
+ * Gets value class.
+ *
+ * @return Value class.
+ */
+ public Class<?> valueClass();
+
+ /**
+ * Gets key class.
+ *
+ * @return Key class.
+ */
+ public Class<?> keyClass();
+
+ /**
+ * Returns {@code true} if string representation of value should be indexed as text.
+ *
+ * @return If string representation of value should be full-text indexed.
+ */
+ public boolean valueTextIndex();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/visor/node/VisorSpisConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/visor/node/VisorSpisConfiguration.java b/modules/core/src/main/java/org/gridgain/grid/kernal/visor/node/VisorSpisConfiguration.java
index 8a6b1b5..4bb65c7 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/visor/node/VisorSpisConfiguration.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/visor/node/VisorSpisConfiguration.java
@@ -315,7 +315,7 @@ public class VisorSpisConfiguration implements Serializable {
/**
* @param indexingSpis New indexing SPIs.
*/
- public void indexingSpis(IgniteBiTuple<String, Map<String, Object>>[] indexingSpis) {
+ public void indexingSpis(IgniteBiTuple<String, Map<String, Object>>... indexingSpis) {
this.indexingSpis = indexingSpis;
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/visor/query/VisorQueryTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/visor/query/VisorQueryTask.java b/modules/core/src/main/java/org/gridgain/grid/kernal/visor/query/VisorQueryTask.java
index 87ce34b..f575969 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/visor/query/VisorQueryTask.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/visor/query/VisorQueryTask.java
@@ -15,11 +15,11 @@ import org.gridgain.grid.cache.GridCache;
import org.gridgain.grid.cache.query.GridCacheQueryFuture;
import org.gridgain.grid.kernal.GridKernal;
import org.gridgain.grid.kernal.processors.cache.query.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.kernal.processors.task.GridInternal;
import org.gridgain.grid.kernal.processors.timeout.GridTimeoutObjectAdapter;
import org.gridgain.grid.kernal.visor.*;
import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.spi.indexing.IndexingFieldMetadata;
import org.gridgain.grid.util.typedef.internal.*;
import java.io.*;
@@ -220,7 +220,7 @@ public class VisorQueryTask extends VisorOneNodeTask<VisorQueryTask.VisorQueryAr
List<Object> firstRow = (List<Object>)fut.next();
- List<IndexingFieldMetadata> meta = ((GridCacheQueryMetadataAware)fut).metadata().get();
+ List<GridQueryFieldMetadata> meta = ((GridCacheQueryMetadataAware)fut).metadata().get();
if (meta == null)
return new IgniteBiTuple<Exception, VisorQueryResultEx>(
@@ -229,7 +229,7 @@ public class VisorQueryTask extends VisorOneNodeTask<VisorQueryTask.VisorQueryAr
VisorQueryField[] names = new VisorQueryField[meta.size()];
for (int i = 0; i < meta.size(); i++) {
- IndexingFieldMetadata col = meta.get(i);
+ GridQueryFieldMetadata col = meta.get(i);
names[i] = new VisorQueryField(col.typeName(), col.fieldName());
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/util/GridUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/util/GridUtils.java b/modules/core/src/main/java/org/gridgain/grid/util/GridUtils.java
index cced666..bdc4c3e 100644
--- a/modules/core/src/main/java/org/gridgain/grid/util/GridUtils.java
+++ b/modules/core/src/main/java/org/gridgain/grid/util/GridUtils.java
@@ -967,6 +967,26 @@ public abstract class GridUtils {
/**
* Creates new instance of a class only if it has an empty constructor (can be non-public).
*
+ * @param cls Class name.
+ * @return Instance.
+ * @throws GridException If failed.
+ */
+ @Nullable public static <T> T newInstance(String cls) throws GridException {
+ Class<?> cls0;
+
+ try {
+ cls0 = Class.forName(cls);
+ }
+ catch (Exception e) {
+ throw new GridException(e);
+ }
+
+ return (T)newInstance(cls0);
+ }
+
+ /**
+ * Creates new instance of a class only if it has an empty constructor (can be non-public).
+ *
* @param cls Class to instantiate.
* @return New instance of the class or {@code null} if empty constructor could not be assigned.
* @throws GridException If failed.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheTxExceptionAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheTxExceptionAbstractSelfTest.java b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheTxExceptionAbstractSelfTest.java
index c156c86..0d4c750 100644
--- a/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheTxExceptionAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheTxExceptionAbstractSelfTest.java
@@ -571,7 +571,7 @@ public abstract class GridCacheTxExceptionAbstractSelfTest extends GridCacheAbst
/**
* Indexing SPI that can fail on demand.
*/
- private static class TestIndexingSpi extends IgniteSpiAdapter implements IndexingSpi {
+ private static class TestIndexingSpi extends IgniteSpiAdapter implements GridIndexingSpi {
/** Fail flag. */
private volatile boolean fail;
@@ -583,63 +583,12 @@ public abstract class GridCacheTxExceptionAbstractSelfTest extends GridCacheAbst
}
/** {@inheritDoc} */
- @Override public <K, V> IndexingFieldsResult queryFields(@Nullable String spaceName, String qry,
- Collection<Object> params, IndexingQueryFilter filters) {
+ @Override public Iterator<?> query(@Nullable String spaceName, Collection<Object> params, @Nullable GridIndexingQueryFilter filters) throws IgniteSpiException {
throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
- @Override public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> query(
- @Nullable String spaceName, String qry, Collection<Object> params, IndexingTypeDescriptor type,
- IndexingQueryFilter filters) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> queryText(
- @Nullable String spaceName, String qry, IndexingTypeDescriptor type,
- IndexingQueryFilter filters) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public long size(@Nullable String spaceName, IndexingTypeDescriptor desc) {
- return 0;
- }
-
- /** {@inheritDoc} */
- @Override public boolean registerType(@Nullable String spaceName, IndexingTypeDescriptor desc) {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public void unregisterType(@Nullable String spaceName, IndexingTypeDescriptor type) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public <K> void onSwap(@Nullable String spaceName, String swapSpaceName, K key) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> void onUnswap(@Nullable String spaceName, K key, V val, byte[] valBytes) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void registerMarshaller(IndexingMarshaller marshaller) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void rebuildIndexes(@Nullable String spaceName, IndexingTypeDescriptor type) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> void store(@Nullable String spaceName, IndexingTypeDescriptor type,
- IndexingEntity<K> key, IndexingEntity<V> val, byte[] ver, long expirationTime)
+ @Override public void store(@Nullable String spaceName, Object key, Object val, long expirationTime)
throws IgniteSpiException {
if (fail) {
fail = false;
@@ -649,19 +598,22 @@ public abstract class GridCacheTxExceptionAbstractSelfTest extends GridCacheAbst
}
/** {@inheritDoc} */
- @Override public <K> boolean remove(@Nullable String spaceName, IndexingEntity<K> k)
+ @Override public void remove(@Nullable String spaceName, Object k)
throws IgniteSpiException {
if (fail) {
fail = false;
throw new IgniteSpiException("Test exception.");
}
+ }
- return true;
+ /** {@inheritDoc} */
+ @Override public void onSwap(@Nullable String spaceName, Object key) throws IgniteSpiException {
+ // No-op.
}
/** {@inheritDoc} */
- @Override public void registerSpace(String spaceName) throws IgniteSpiException {
+ @Override public void onUnswap(@Nullable String spaceName, Object key, Object val) throws IgniteSpiException {
// No-op.
}
[10/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryManager.java
index d221c47..dbb2665 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryManager.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryManager.java
@@ -21,10 +21,10 @@ import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.managers.eventstorage.*;
-import org.gridgain.grid.kernal.managers.indexing.*;
import org.gridgain.grid.kernal.processors.cache.*;
import org.gridgain.grid.kernal.processors.cache.datastructures.*;
import org.gridgain.grid.kernal.processors.cache.distributed.dht.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.kernal.processors.task.*;
import org.gridgain.grid.util.*;
import org.gridgain.grid.util.future.*;
@@ -36,7 +36,6 @@ import org.jdk8.backport.*;
import org.jetbrains.annotations.*;
import java.io.*;
-import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import java.util.concurrent.*;
@@ -52,10 +51,7 @@ import static org.gridgain.grid.kernal.processors.cache.query.GridCacheQueryType
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapter<K, V> {
/** */
- protected GridIndexingManager idxMgr;
-
- /** Indexing SPI name. */
- private String spi;
+ protected GridQueryProcessor idxProc;
/** */
private String space;
@@ -82,8 +78,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/** {@inheritDoc} */
@Override public void start0() throws GridException {
- idxMgr = cctx.kernalContext().indexing();
- spi = cctx.config().getIndexingSpiName();
+ idxProc = cctx.kernalContext().query();
space = cctx.name();
maxIterCnt = cctx.config().getMaximumQueryIteratorCount();
@@ -170,7 +165,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
throw new IllegalStateException("Failed to get size (grid is stopping).");
try {
- return idxMgr.size(spi, space, valType);
+ return idxProc.size(space, valType);
}
finally {
leaveBusy();
@@ -198,7 +193,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
throw new IllegalStateException("Failed to rebuild indexes (grid is stopping).");
try {
- return idxMgr.rebuildIndexes(spi, space, typeName);
+ return idxProc.rebuildIndexes(space, typeName);
}
finally {
leaveBusy();
@@ -215,7 +210,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
throw new IllegalStateException("Failed to rebuild indexes (grid is stopping).");
try {
- return idxMgr.rebuildAllIndexes(spi);
+ return idxProc.rebuildAllIndexes();
}
finally {
leaveBusy();
@@ -260,14 +255,14 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
*
* @param swapSpaceName Swap space name.
* @param key Key.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
+ * @throws GridException If failed.
*/
- public void onSwap(String swapSpaceName, K key) throws IgniteSpiException {
+ public void onSwap(String swapSpaceName, K key) throws GridException {
if (!enterBusy())
return; // Ignore index update when node is stopping.
try {
- idxMgr.onSwap(spi, space, swapSpaceName, key);
+ idxProc.onSwap(space, key);
}
finally {
leaveBusy();
@@ -280,14 +275,14 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @param key Key.
* @param val Value
* @param valBytes Value bytes.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
+ * @throws GridException If failed.
*/
- public void onUnswap(K key, V val, byte[] valBytes) throws IgniteSpiException {
+ public void onUnswap(K key, V val, byte[] valBytes) throws GridException {
if (!enterBusy())
return; // Ignore index update when node is stopping.
try {
- idxMgr.onUnswap(spi, space, key, val, valBytes);
+ idxProc.onUnswap(space, key, val, valBytes);
}
finally {
leaveBusy();
@@ -329,7 +324,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
if (val == null)
val = cctx.marshaller().unmarshal(valBytes, cctx.deploy().globalLoader());
- idxMgr.store(spi, space, key, keyBytes, val, valBytes, CU.versionToBytes(ver), expirationTime);
+ idxProc.store(space, key, keyBytes, val, valBytes, CU.versionToBytes(ver), expirationTime);
}
finally {
invalidateResultCache();
@@ -341,21 +336,20 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/**
* @param key Key.
* @param keyBytes Byte array with key value.
- * @return {@code true} if key was found and removed, otherwise {@code false}.
* @throws GridException Thrown in case of any errors.
*/
@SuppressWarnings("SimplifiableIfStatement")
- public boolean remove(K key, @Nullable byte[] keyBytes) throws GridException {
+ public void remove(K key, @Nullable byte[] keyBytes) throws GridException {
assert key != null;
if (!cctx.config().isQueryIndexEnabled() && !(key instanceof GridCacheInternal))
- return false; // No-op.
+ return; // No-op.
if (!enterBusy())
- return false; // Ignore index update when node is stopping.
+ return; // Ignore index update when node is stopping.
try {
- return idxMgr.remove(spi, space, key, keyBytes);
+ idxProc.remove(space, key);
}
finally {
invalidateResultCache();
@@ -374,7 +368,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
return; // Ignore index update when node is stopping.
try {
- idxMgr.onUndeploy(space, ldr);
+ idxProc.onUndeploy(space, ldr);
}
catch (GridException e) {
throw new GridRuntimeException(e);
@@ -473,7 +467,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
else
res = new QueryResult<>(qry.type(), recipient);
- GridCloseableIterator<IndexingKeyValueRow<K, V>> iter;
+ GridCloseableIterator<IgniteBiTuple<K, V>> iter;
try {
switch (qry.type()) {
@@ -494,8 +488,8 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
taskName));
}
- iter = idxMgr.query(spi, space, qry.clause(), F.asList(args),
- qry.queryClassName(), qry.includeBackups(), projectionFilter(qry));
+ iter = idxProc.query(space, qry.clause(), F.asList(args),
+ qry.queryClassName(), filter(qry));
break;
@@ -537,8 +531,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
taskName));
}
- iter = idxMgr.queryText(spi, space, qry.clause(), qry.queryClassName(),
- qry.includeBackups(), projectionFilter(qry));
+ iter = idxProc.queryText(space, qry.clause(), qry.queryClassName(), filter(qry));
break;
@@ -583,56 +576,92 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
boolean loc, @Nullable UUID subjId, @Nullable String taskName, Object recipient) throws GridException {
assert qry != null;
- if (qry.clause() == null) {
- assert !loc;
+ FieldsResult res;
- throw new GridException("Received next page request after iterator was removed. " +
- "Consider increasing maximum number of stored iterators (see " +
- "GridCacheConfiguration.getMaximumQueryIteratorCount() configuration property).");
- }
+ T2<String, List<Object>> resKey = null;
- assert qry.type() == SQL_FIELDS;
+ if (qry.type() == SQL_FIELDS) {
+ if (qry.clause() == null) {
+ assert !loc;
- if (cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
- cctx.gridEvents().record(new IgniteCacheQueryExecutedEvent<>(
- cctx.localNode(),
- "SQL fields query executed.",
- EVT_CACHE_QUERY_EXECUTED,
- org.gridgain.grid.cache.query.GridCacheQueryType.SQL_FIELDS,
- cctx.namex(),
- null,
- qry.clause(),
- null,
- null,
- args,
- subjId,
- taskName));
- }
+ throw new GridException("Received next page request after iterator was removed. " +
+ "Consider increasing maximum number of stored iterators (see " +
+ "GridCacheConfiguration.getMaximumQueryIteratorCount() configuration property).");
+ }
- T2<String, List<Object>> resKey = new T2<>(qry.clause(), F.asList(args));
+ if (cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
+ cctx.gridEvents().record(new IgniteCacheQueryExecutedEvent<>(
+ cctx.localNode(),
+ "SQL fields query executed.",
+ EVT_CACHE_QUERY_EXECUTED,
+ org.gridgain.grid.cache.query.GridCacheQueryType.SQL_FIELDS,
+ cctx.namex(),
+ null,
+ qry.clause(),
+ null,
+ null,
+ args,
+ subjId,
+ taskName));
+ }
- FieldsResult res = (FieldsResult)qryResCache.get(resKey);
+ // Attempt to get result from cache.
+ resKey = new T2<>(qry.clause(), F.asList(args));
- if (res != null && res.addRecipient(recipient))
- return res;
+ res = (FieldsResult)qryResCache.get(resKey);
+
+ if (res != null && res.addRecipient(recipient))
+ return res; // Cached result found.
+
+ res = new FieldsResult(recipient);
+
+ if (qryResCache.putIfAbsent(resKey, res) != null)
+ resKey = null; // Failed to cache result.
+ }
+ else {
+ assert qry.type() == SPI;
- res = new FieldsResult(recipient);
+ if (cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
+ cctx.gridEvents().record(new IgniteCacheQueryExecutedEvent<>(
+ cctx.localNode(),
+ "SPI query executed.",
+ EVT_CACHE_QUERY_EXECUTED,
+ org.gridgain.grid.cache.query.GridCacheQueryType.SPI,
+ cctx.namex(),
+ null,
+ null,
+ null,
+ null,
+ args,
+ subjId,
+ taskName));
+ }
- boolean cached = qryResCache.putIfAbsent(resKey, res) == null;
+ res = new FieldsResult(recipient);
+ }
try {
- IndexingFieldsResult qryRes = idxMgr.queryFields(spi, space, qry.clause(), F.asList(args),
- qry.includeBackups(), projectionFilter(qry));
+ if (qry.type() == SPI) {
+ IgniteSpiCloseableIterator<?> iter = cctx.kernalContext().indexing().query(space, F.asList(args),
+ filter(qry));
+
+ res.onDone(iter);
+ }
+ else {
+ assert qry.type() == SQL_FIELDS;
+
+ GridQueryFieldsResult qryRes = idxProc.queryFields(space, qry.clause(), F.asList(args), filter(qry));
- res.metaData(qryRes.metaData());
+ res.metaData(qryRes.metaData());
- res.onDone(qryRes.iterator());
+ res.onDone(qryRes.iterator());
+ }
}
catch (Exception e) {
res.onDone(e);
}
finally {
- if (cached)
+ if (resKey != null)
qryResCache.remove(resKey, res);
}
@@ -643,7 +672,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @param qry Query.
* @return Cache set items iterator.
*/
- private GridCloseableIterator<IndexingKeyValueRow<K, V>> setIterator(GridCacheQueryAdapter<?> qry) {
+ private GridCloseableIterator<IgniteBiTuple<K, V>> setIterator(GridCacheQueryAdapter<?> qry) {
final GridSetQueryPredicate filter = (GridSetQueryPredicate)qry.scanFilter();
filter.init(cctx);
@@ -655,11 +684,11 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
if (data == null)
data = Collections.emptyList();
- final GridIterator<IndexingKeyValueRow<K, V>> it = F.iterator(
+ final GridIterator<IgniteBiTuple<K, V>> it = F.iterator(
data,
- new C1<GridCacheSetItemKey, IndexingKeyValueRow<K, V>>() {
- @Override public IndexingKeyValueRow<K, V> apply(GridCacheSetItemKey e) {
- return new IndexingKeyValueRowAdapter<>((K)e.item(), (V)Boolean.TRUE);
+ new C1<GridCacheSetItemKey, IgniteBiTuple<K, V>>() {
+ @Override public IgniteBiTuple<K, V> apply(GridCacheSetItemKey e) {
+ return new IgniteBiTuple<>((K)e.item(), (V)Boolean.TRUE);
}
},
true,
@@ -669,12 +698,12 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
});
- return new GridCloseableIteratorAdapter<IndexingKeyValueRow<K, V>>() {
+ return new GridCloseableIteratorAdapter<IgniteBiTuple<K, V>>() {
@Override protected boolean onHasNext() {
return it.hasNext();
}
- @Override protected IndexingKeyValueRow<K, V> onNext() {
+ @Override protected IgniteBiTuple<K, V> onNext() {
return it.next();
}
@@ -694,7 +723,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @throws GridException If failed to get iterator.
*/
@SuppressWarnings({"unchecked"})
- private GridCloseableIterator<IndexingKeyValueRow<K, V>> scanIterator(final GridCacheQueryAdapter<?> qry)
+ private GridCloseableIterator<IgniteBiTuple<K, V>> scanIterator(final GridCacheQueryAdapter<?> qry)
throws GridException {
IgnitePredicate<GridCacheEntry<K, V>> filter = null;
@@ -717,8 +746,8 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
injectResources(keyValFilter);
- GridIterator<IndexingKeyValueRow<K, V>> heapIt = new GridIteratorAdapter<IndexingKeyValueRow<K, V>>() {
- private IndexingKeyValueRow<K, V> next;
+ GridIterator<IgniteBiTuple<K, V>> heapIt = new GridIteratorAdapter<IgniteBiTuple<K, V>>() {
+ private IgniteBiTuple<K, V> next;
private Iterator<K> iter = prj.keySet().iterator();
@@ -730,11 +759,11 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
return next != null;
}
- @Override public IndexingKeyValueRow<K, V> nextX() {
+ @Override public IgniteBiTuple<K, V> nextX() {
if (next == null)
throw new NoSuchElementException();
- IndexingKeyValueRow<K, V> next0 = next;
+ IgniteBiTuple<K, V> next0 = next;
advance();
@@ -766,7 +795,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
next = next0 != null ?
- new IndexingKeyValueRowAdapter<>(next0.getKey(), next0.getValue()) :
+ new IgniteBiTuple<>(next0.getKey(), next0.getValue()) :
null;
}
@@ -781,10 +810,10 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
};
- final GridIterator<IndexingKeyValueRow<K, V>> it;
+ final GridIterator<IgniteBiTuple<K, V>> it;
if (cctx.isSwapOrOffheapEnabled()) {
- List<GridIterator<IndexingKeyValueRow<K, V>>> iters = new ArrayList<>(3);
+ List<GridIterator<IgniteBiTuple<K, V>>> iters = new ArrayList<>(3);
iters.add(heapIt);
@@ -799,12 +828,12 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
else
it = heapIt;
- return new GridCloseableIteratorAdapter<IndexingKeyValueRow<K, V>>() {
+ return new GridCloseableIteratorAdapter<IgniteBiTuple<K, V>>() {
@Override protected boolean onHasNext() {
return it.hasNext();
}
- @Override protected IndexingKeyValueRow<K, V> onNext() {
+ @Override protected IgniteBiTuple<K, V> onNext() {
return it.next();
}
@@ -819,7 +848,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @return Swap iterator.
* @throws GridException If failed.
*/
- private GridIterator<IndexingKeyValueRow<K, V>> swapIterator(GridCacheQueryAdapter<?> qry)
+ private GridIterator<IgniteBiTuple<K, V>> swapIterator(GridCacheQueryAdapter<?> qry)
throws GridException {
IgnitePredicate<GridCacheEntry<Object, Object>> prjPred = qry.projectionFilter();
@@ -834,7 +863,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @param qry Query.
* @return Offheap iterator.
*/
- private GridIterator<IndexingKeyValueRow<K, V>> offheapIterator(GridCacheQueryAdapter<?> qry) {
+ private GridIterator<IgniteBiTuple<K, V>> offheapIterator(GridCacheQueryAdapter<?> qry) {
IgnitePredicate<GridCacheEntry<Object, Object>> prjPred = qry.projectionFilter();
IgniteBiPredicate<K, V> filter = qry.scanFilter();
@@ -858,7 +887,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @param keepPortable Keep portable flag.
* @return Iterator.
*/
- private GridIteratorAdapter<IndexingKeyValueRow<K, V>> scanIterator(
+ private GridIteratorAdapter<IgniteBiTuple<K, V>> scanIterator(
@Nullable final Iterator<Map.Entry<byte[], byte[]>> it,
@Nullable final IgnitePredicate<GridCacheEntry<Object, Object>> prjPred,
@Nullable final IgniteBiPredicate<K, V> filter,
@@ -866,8 +895,8 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
if (it == null)
return new GridEmptyCloseableIterator<>();
- return new GridIteratorAdapter<IndexingKeyValueRow<K, V>>() {
- private IndexingKeyValueRow<K, V> next;
+ return new GridIteratorAdapter<IgniteBiTuple<K, V>>() {
+ private IgniteBiTuple<K, V> next;
{
advance();
@@ -877,11 +906,11 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
return next != null;
}
- @Override public IndexingKeyValueRow<K, V> nextX() {
+ @Override public IgniteBiTuple<K, V> nextX() {
if (next == null)
throw new NoSuchElementException();
- IndexingKeyValueRow<K, V> next0 = next;
+ IgniteBiTuple<K, V> next0 = next;
advance();
@@ -913,7 +942,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
continue;
}
- next = new IndexingKeyValueRowAdapter<>(e.key(), e.value());
+ next = new IgniteBiTuple<>(e.key(), e.value());
break;
}
@@ -962,8 +991,8 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
try {
// Preparing query closures.
IgnitePredicate<GridCacheEntry<Object, Object>> prjFilter = qryInfo.projectionPredicate();
- IgniteClosure<List<?>, Object> trans = (IgniteClosure<List<?>, Object>)qryInfo.transformer();
- IgniteReducer<List<?>, Object> rdc = (IgniteReducer<List<?>, Object>)qryInfo.reducer();
+ IgniteClosure<Object, Object> trans = (IgniteClosure<Object, Object>)qryInfo.transformer();
+ IgniteReducer<Object, Object> rdc = (IgniteReducer<Object, Object>)qryInfo.reducer();
injectResources(prjFilter);
injectResources(trans);
@@ -974,7 +1003,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
int pageSize = qry.pageSize();
Collection<Object> data = null;
- Collection<List<IndexingEntity<?>>> entities = null;
+ Collection<Object> entities = null;
if (qryInfo.local() || rdc != null || cctx.isLocalNode(qryInfo.senderId()))
data = new ArrayList<>(pageSize);
@@ -989,14 +1018,14 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
fieldsQueryResult(qryInfo, taskName);
// If metadata needs to be returned to user and cleaned from internal fields - copy it.
- List<IndexingFieldMetadata> meta = qryInfo.includeMetaData() ?
- (res.metaData() != null ? new ArrayList<>(res.metaData()) : null) :
+ List<GridQueryFieldMetadata> meta = qryInfo.includeMetaData() ?
+ (res.metaData() != null ? new ArrayList<GridQueryFieldMetadata>(res.metaData()) : null) :
res.metaData();
if (!qryInfo.includeMetaData())
meta = null;
- GridCloseableIterator<List<IndexingEntity<?>>> it = new GridSpiCloseableIteratorWrapper<>(
+ GridCloseableIterator<?> it = new GridSpiCloseableIteratorWrapper<Object>(
res.iterator(recipient(qryInfo.senderId(), qryInfo.requestId())));
if (log.isDebugEnabled())
@@ -1015,7 +1044,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
boolean metaSent = false;
while (!Thread.currentThread().isInterrupted() && it.hasNext()) {
- List<IndexingEntity<?>> row = it.next();
+ Object row = it.next();
// Query is cancelled.
if (row == null) {
@@ -1041,26 +1070,17 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
null,
null,
null,
- F.viewListReadOnly(row, new CX1<IndexingEntity<?>, Object>() {
- @Override public Object applyx(IndexingEntity<?> ent) throws GridException {
- return ent.value();
- }
- })));
+ row));
}
if ((qryInfo.local() || rdc != null || cctx.isLocalNode(qryInfo.senderId()))) {
- List<Object> fields = new ArrayList<>(row.size());
-
- for (IndexingEntity<?> ent : row)
- fields.add(ent.value());
-
// Reduce.
if (rdc != null) {
- if (!rdc.collect(fields))
+ if (!rdc.collect(row))
break;
}
else
- data.add(fields);
+ data.add(row);
}
else
entities.add(row);
@@ -1153,7 +1173,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
String taskName = cctx.kernalContext().task().resolveTaskName(qry.taskHash());
- IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> iter;
+ IgniteSpiCloseableIterator<IgniteBiTuple<K, V>> iter;
GridCacheQueryType type;
QueryResult<K, V> res;
@@ -1182,7 +1202,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
long topVer = cctx.affinity().affinityTopologyVersion();
while (!Thread.currentThread().isInterrupted() && iter.hasNext()) {
- IndexingKeyValueRow<K, V> row = iter.next();
+ IgniteBiTuple<K, V> row = iter.next();
// Query is cancelled.
if (row == null) {
@@ -1191,7 +1211,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
break;
}
- K key = row.key().value();
+ K key = row.getKey();
// Filter backups for SCAN queries. Other types are filtered in indexing manager.
if (!cctx.isReplicated() && cctx.config().getCacheMode() != LOCAL && qry.type() == SCAN &&
@@ -1204,11 +1224,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
continue;
}
- IndexingEntity<V> v = row.value();
-
- assert v != null && v.hasValue();
-
- V val = v.value();
+ V val = row.getValue();
if (log.isDebugEnabled())
log.debug("Record [key=" + key + ", val=" + val + ", incBackups=" +
@@ -1589,6 +1605,8 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
if (fut != null) {
+ assert fut.isDone();
+
try {
fut.get().closeIfNotShared(recipient(sndId, reqId));
}
@@ -1623,34 +1641,12 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @return {@code true} if page was processed right.
*/
protected abstract boolean onFieldsPageReady(boolean loc, GridCacheQueryInfo qryInfo,
- @Nullable List<IndexingFieldMetadata> metaData,
- @Nullable Collection<List<IndexingEntity<?>>> entities,
+ @Nullable List<GridQueryFieldMetadata> metaData,
+ @Nullable Collection<?> entities,
@Nullable Collection<?> data,
boolean finished, @Nullable Throwable e);
/**
- * Checks if a given query class is a Java primitive or wrapper
- * and throws {@link IllegalStateException} if there is configured {@code GridH2IndexingSpi}
- * with disabled {@code GridH2IndexingSpi#isDefaultIndexPrimitiveKey()}.
- *
- * @param cls Query class. May be {@code null}.
- * @throws IllegalStateException If checking failed.
- */
- private void checkPrimitiveIndexEnabled(@Nullable Class<?> cls) {
- if (cls == null)
- return;
-
- if (GridUtils.isPrimitiveOrWrapper(cls)) {
- for (IndexingSpi indexingSpi : cctx.gridConfig().getIndexingSpi()) {
- if (!isDefaultIndexPrimitiveKey(indexingSpi))
- throw new IllegalStateException("Invalid use of primitive class type in queries when " +
- "GridH2IndexingSpi.isDefaultIndexPrimitiveKey() is disabled " +
- "(consider enabling indexing for primitive types).");
- }
- }
- }
-
- /**
* Gets cache queries metrics.
*
* @return Cache queries metrics.
@@ -1685,7 +1681,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
throw new IllegalStateException("Failed to get metadata (grid is stopping).");
try {
- Callable<Collection<CacheSqlMetadata>> job = new MetadataJob(spi);
+ Callable<Collection<CacheSqlMetadata>> job = new MetadataJob();
// Remote nodes that have current cache.
Collection<ClusterNode> nodes = F.view(cctx.discovery().remoteNodes(), new P1<ClusterNode>() {
@@ -1747,7 +1743,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
* @return Filter.
*/
@SuppressWarnings("unchecked")
- @Nullable private IndexingQueryFilter projectionFilter(GridCacheQueryAdapter<?> qry) {
+ @Nullable private GridIndexingQueryFilter projectionFilter(GridCacheQueryAdapter<?> qry) {
assert qry != null;
final IgnitePredicate<GridCacheEntry<Object, Object>> prjFilter = qry.projectionFilter();
@@ -1755,8 +1751,8 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
if (prjFilter == null || F.isAlwaysTrue(prjFilter))
return null;
- return new IndexingQueryFilter() {
- @Nullable @Override public IgniteBiPredicate<K, V> forSpace(String spaceName) throws GridException {
+ return new GridIndexingQueryFilter() {
+ @Nullable @Override public IgniteBiPredicate<K, V> forSpace(String spaceName) {
if (!F.eq(space, spaceName))
return null;
@@ -1777,23 +1773,73 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
/**
- * @param indexingSpi Indexing SPI.
- * @return {@code True} if given SPI is GridH2IndexingSpi with enabled property {@code isDefaultIndexPrimitiveKey}.
+ * @param <K> Key type.
+ * @param <V> Value type.
+ * @return Predicate.
+ * @param includeBackups Include backups.
*/
- private static boolean isDefaultIndexPrimitiveKey(IndexingSpi indexingSpi) {
- if (indexingSpi.getClass().getName().equals(GridComponentType.H2_INDEXING.className())) {
- try {
- Method method = indexingSpi.getClass().getMethod("isDefaultIndexPrimitiveKey");
+ @SuppressWarnings("unchecked")
+ @Nullable public <K, V> GridIndexingQueryFilter backupsFilter(boolean includeBackups) {
+ if (includeBackups)
+ return null;
- return (Boolean)method.invoke(indexingSpi);
- }
- catch (Exception e) {
- throw new GridRuntimeException("Failed to invoke 'isDefaultIndexPrimitiveKey' method " +
- "on GridH2IndexingSpi.", e);
+ return new GridIndexingQueryFilter() {
+ @Nullable @Override public IgniteBiPredicate<K, V> forSpace(final String spaceName) {
+ final GridKernalContext ctx = cctx.kernalContext();
+
+ final GridCacheAdapter<Object, Object> cache = ctx.cache().internalCache(spaceName);
+
+ if (cache.context().isReplicated() || cache.configuration().getBackups() == 0)
+ return null;
+
+ return new IgniteBiPredicate<K, V>() {
+ @Override public boolean apply(K k, V v) {
+ return cache.context().affinity().primary(ctx.discovery().localNode(), k, -1);
+ }
+ };
}
- }
+ };
+ }
- return false;
+ /**
+ * @param qry Query.
+ * @return Filter.
+ */
+ private GridIndexingQueryFilter filter(GridCacheQueryAdapter<?> qry) {
+ return and(backupsFilter(qry.includeBackups()), projectionFilter(qry));
+ }
+
+ /**
+ * @param f1 First filter.
+ * @param f2 Second filter.
+ * @return And filter of the given two.
+ */
+ @Nullable private static GridIndexingQueryFilter and(@Nullable final GridIndexingQueryFilter f1,
+ @Nullable final GridIndexingQueryFilter f2) {
+ if (f1 == null)
+ return f2;
+
+ if (f2 == null)
+ return f1;
+
+ return new GridIndexingQueryFilter() {
+ @Nullable @Override public <K, V> IgniteBiPredicate<K, V> forSpace(String spaceName) {
+ final IgniteBiPredicate<K, V> fltr1 = f1.forSpace(spaceName);
+ final IgniteBiPredicate<K, V> fltr2 = f2.forSpace(spaceName);
+
+ if (fltr1 == null)
+ return fltr2;
+
+ if (fltr2 == null)
+ return fltr1;
+
+ return new IgniteBiPredicate<K, V>() {
+ @Override public boolean apply(K k, V v) {
+ return fltr1.apply(k, v) && fltr2.apply(k, v);
+ }
+ };
+ }
+ };
}
/**
@@ -1825,16 +1871,6 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
@IgniteInstanceResource
private Ignite ignite;
- /** Indexing SPI name. */
- private final String spiName;
-
- /**
- * @param spiName Indexing SPI name.
- */
- private MetadataJob(@Nullable String spiName) {
- this.spiName = spiName;
- }
-
/** {@inheritDoc} */
@Override public Collection<CacheSqlMetadata> call() {
final GridKernalContext ctx = ((GridKernal) ignite).context();
@@ -1847,15 +1883,14 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
},
new P1<GridCache<?, ?>>() {
@Override public boolean apply(GridCache<?, ?> c) {
- return !CU.UTILITY_CACHE_NAME.equals(c.name()) &&
- F.eq(spiName, c.configuration().getIndexingSpiName());
+ return !CU.UTILITY_CACHE_NAME.equals(c.name());
}
}
);
return F.transform(cacheNames, new C1<String, CacheSqlMetadata>() {
@Override public CacheSqlMetadata apply(String cacheName) {
- Collection<IndexingTypeDescriptor> types = ctx.indexing().types(cacheName);
+ Collection<GridQueryTypeDescriptor> types = ctx.query().types(cacheName);
Collection<String> names = U.newHashSet(types.size());
Map<String, String> keyClasses = U.newHashMap(types.size());
@@ -1863,7 +1898,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
Map<String, Map<String, String>> fields = U.newHashMap(types.size());
Map<String, Collection<GridCacheSqlIndexMetadata>> indexes = U.newHashMap(types.size());
- for (IndexingTypeDescriptor type : types) {
+ for (GridQueryTypeDescriptor type : types) {
// Filter internal types (e.g., data structures).
if (type.name().startsWith("GridCache"))
continue;
@@ -1892,11 +1927,11 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
Collection<GridCacheSqlIndexMetadata> indexesCol =
new ArrayList<>(type.indexes().size());
- for (Map.Entry<String, IndexDescriptor> e : type.indexes().entrySet()) {
- IndexDescriptor desc = e.getValue();
+ for (Map.Entry<String, GridQueryIndexDescriptor> e : type.indexes().entrySet()) {
+ GridQueryIndexDescriptor desc = e.getValue();
// Add only SQL indexes.
- if (desc.type() == IndexType.SORTED) {
+ if (desc.type() == GridQueryIndexType.SORTED) {
Collection<String> idxFields = e.getValue().fields();
Collection<String> descendings = new LinkedList<>();
@@ -2142,8 +2177,9 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
/**
+ *
*/
- private static class QueryResult<K, V> extends CachedResult<IndexingKeyValueRow<K, V>> {
+ private static class QueryResult<K, V> extends CachedResult<IgniteBiTuple<K, V>> {
/** */
private static final long serialVersionUID = 0L;
@@ -2171,12 +2207,12 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/**
*
*/
- private static class FieldsResult extends CachedResult<List<IndexingEntity<?>>> {
+ private static class FieldsResult<Q> extends CachedResult<Q> {
/** */
private static final long serialVersionUID = 0L;
/** */
- private List<IndexingFieldMetadata> meta;
+ private List<GridQueryFieldMetadata> meta;
/**
* @param recipient ID of the recipient.
@@ -2188,7 +2224,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/**
* @return Metadata.
*/
- public List<IndexingFieldMetadata> metaData() throws GridException {
+ public List<GridQueryFieldMetadata> metaData() throws GridException {
get(); // Ensure that result is ready.
return meta;
@@ -2197,7 +2233,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
/**
* @param meta Metadata.
*/
- public void metaData(List<IndexingFieldMetadata> meta) {
+ public void metaData(List<GridQueryFieldMetadata> meta) {
this.meta = meta;
}
}
@@ -2387,7 +2423,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
*
*/
private class OffheapIteratorClosure
- extends CX2<T2<Long, Integer>, T2<Long, Integer>, IndexingKeyValueRow<K, V>> {
+ extends CX2<T2<Long, Integer>, T2<Long, Integer>, IgniteBiTuple<K, V>> {
/** */
private static final long serialVersionUID = 7410163202728985912L;
@@ -2417,7 +2453,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
/** {@inheritDoc} */
- @Nullable @Override public IndexingKeyValueRow<K, V> applyx(T2<Long, Integer> keyPtr,
+ @Nullable @Override public IgniteBiTuple<K, V> applyx(T2<Long, Integer> keyPtr,
T2<Long, Integer> valPtr)
throws GridException {
LazyOffheapEntry e = new LazyOffheapEntry(keyPtr, valPtr);
@@ -2437,7 +2473,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
return null;
}
- return new IndexingKeyValueRowAdapter<>(e.key(), (V)cctx.unwrapTemporary(e.value())) ;
+ return new IgniteBiTuple<>(e.key(), (V)cctx.unwrapTemporary(e.value())) ;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryMetadataAware.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryMetadataAware.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryMetadataAware.java
index 2507369..66060e0 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryMetadataAware.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryMetadataAware.java
@@ -9,8 +9,8 @@
package org.gridgain.grid.kernal.processors.cache.query;
+import org.gridgain.grid.kernal.processors.query.*;
import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
import java.util.*;
@@ -21,5 +21,5 @@ public interface GridCacheQueryMetadataAware {
/**
* @return Future to retrieve metadata.
*/
- public IgniteFuture<List<IndexingFieldMetadata>> metadata();
+ public IgniteFuture<List<GridQueryFieldMetadata>> metadata();
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryRequest.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryRequest.java
index d76b4f7..221eebb 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryRequest.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryRequest.java
@@ -205,8 +205,8 @@ public class GridCacheQueryRequest<K, V> extends GridCacheMessage<K, V> implemen
int taskHash
) {
assert type != null || fields;
- assert clause != null || (type == SCAN || type == SET);
- assert clsName != null || fields || type == SCAN || type == SET;
+ assert clause != null || (type == SCAN || type == SET || type == SPI);
+ assert clsName != null || fields || type == SCAN || type == SET || type == SPI;
this.cacheId = cacheId;
this.id = id;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryResponse.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryResponse.java
index 0564d2a..479f2e8 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryResponse.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryResponse.java
@@ -9,11 +9,10 @@
package org.gridgain.grid.kernal.processors.cache.query;
-import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.direct.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
@@ -54,7 +53,7 @@ public class GridCacheQueryResponse<K, V> extends GridCacheMessage<K, V> impleme
/** */
@GridToStringInclude
@GridDirectTransient
- private List<IndexingFieldMetadata> metadata;
+ private List<GridQueryFieldMetadata> metadata;
/** */
@GridDirectCollection(byte[].class)
@@ -105,7 +104,7 @@ public class GridCacheQueryResponse<K, V> extends GridCacheMessage<K, V> impleme
errBytes = ctx.marshaller().marshal(err);
metaDataBytes = marshalCollection(metadata, ctx);
- dataBytes = fields ? marshalFieldsCollection(data, ctx) : marshalCollection(data, ctx);
+ dataBytes = marshalCollection(data, ctx);
if (ctx.deploymentEnabled() && !F.isEmpty(data)) {
for (Object o : data) {
@@ -127,20 +126,20 @@ public class GridCacheQueryResponse<K, V> extends GridCacheMessage<K, V> impleme
err = ctx.marshaller().unmarshal(errBytes, ldr);
metadata = unmarshalCollection(metaDataBytes, ctx, ldr);
- data = fields ? unmarshalFieldsCollection(dataBytes, ctx, ldr) : unmarshalCollection(dataBytes, ctx, ldr);
+ data = unmarshalCollection(dataBytes, ctx, ldr);
}
/**
* @return Metadata.
*/
- public List<IndexingFieldMetadata> metadata() {
+ public List<GridQueryFieldMetadata> metadata() {
return metadata;
}
/**
* @param metadata Metadata.
*/
- public void metadata(@Nullable List<IndexingFieldMetadata> metadata) {
+ public void metadata(@Nullable List<GridQueryFieldMetadata> metadata) {
this.metadata = metadata;
}
@@ -195,128 +194,6 @@ public class GridCacheQueryResponse<K, V> extends GridCacheMessage<K, V> impleme
}
/** {@inheritDoc} */
- @SuppressWarnings("TypeMayBeWeakened")
- @Nullable private Collection<byte[]> marshalFieldsCollection(@Nullable Collection<Object> col,
- GridCacheSharedContext<K, V> ctx) throws GridException {
- assert ctx != null;
-
- if (col == null)
- return null;
-
- Collection<List<Object>> col0 = new ArrayList<>(col.size());
-
- for (Object o : col) {
- List<IndexingEntity<?>> list = (List<IndexingEntity<?>>)o;
- List<Object> list0 = new ArrayList<>(list.size());
-
- for (IndexingEntity<?> ent : list) {
- if (ent.bytes() != null)
- list0.add(ent.bytes());
- else {
- if (ctx.deploymentEnabled())
- prepareObject(ent.value(), ctx);
-
- list0.add(CU.marshal(ctx, ent.value()));
- }
- }
-
- col0.add(list0);
- }
-
- return marshalCollection(col0, ctx);
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("TypeMayBeWeakened")
- @Nullable private Collection<Object> unmarshalFieldsCollection(@Nullable Collection<byte[]> byteCol,
- GridCacheSharedContext<K, V> ctx, ClassLoader ldr) throws GridException {
- assert ctx != null;
- assert ldr != null;
-
- Collection<Object> col = unmarshalCollection(byteCol, ctx, ldr);
- Collection<Object> col0 = null;
-
- if (col != null) {
- col0 = new ArrayList<>(col.size());
-
- for (Object o : col) {
- List<Object> list = (List<Object>)o;
- List<Object> list0 = new ArrayList<>(list.size());
-
- for (Object obj : list)
- list0.add(obj != null ? ctx.marshaller().unmarshal((byte[])obj, ldr) : null);
-
- col0.add(list0);
- }
- }
-
- return col0;
- }
-
- /**
- * @param out Object output.
- * @throws IOException If failed.
- */
- @SuppressWarnings("TypeMayBeWeakened")
- private void writeFieldsCollection(ObjectOutput out) throws IOException {
- assert fields;
-
- out.writeInt(data != null ? data.size() : -1);
-
- if (data == null)
- return;
-
- for (Object o : data) {
- List<IndexingEntity<?>> list = (List<IndexingEntity<?>>)o;
-
- out.writeInt(list.size());
-
- for (IndexingEntity<?> idxEnt : list) {
- try {
- out.writeObject(idxEnt.value());
- }
- catch (IgniteSpiException e) {
- throw new IOException("Failed to write indexing entity: " + idxEnt, e);
- }
- }
- }
- }
-
- /**
- * @param in Object input.
- * @return Read collection.
- * @throws IOException If failed.
- * @throws ClassNotFoundException If failed.
- */
- private Collection<Object> readFieldsCollection(ObjectInput in) throws IOException, ClassNotFoundException {
- assert fields;
-
- int size = in.readInt();
-
- if (size == -1)
- return null;
-
- Collection<Object> res = new ArrayList<>(size);
-
- for (int i = 0; i < size; i++) {
- int size0 = in.readInt();
-
- Collection<Object> col = new ArrayList<>(size0);
-
- for (int j = 0; j < size0; j++)
- col.add(in.readObject());
-
- assert col.size() == size0;
-
- res.add(col);
- }
-
- assert res.size() == size;
-
- return res;
- }
-
- /** {@inheritDoc} */
@SuppressWarnings({"CloneDoesntCallSuperClone", "CloneCallsConstructors"})
@Override public GridTcpCommunicationMessageAdapter clone() {
GridCacheQueryResponse _clone = new GridCacheQueryResponse();
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryType.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryType.java
index d57fcde..fbcd6e5 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryType.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryType.java
@@ -19,6 +19,11 @@ import org.jetbrains.annotations.*;
*/
public enum GridCacheQueryType {
/**
+ * User provided indexing SPI based query.
+ */
+ SPI,
+
+ /**
* Fully scans cache returning only entries that pass certain filters.
*/
SCAN,
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheSqlMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheSqlMetadata.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheSqlMetadata.java
index cd47b0d..3ec5cb4 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheSqlMetadata.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheSqlMetadata.java
@@ -9,6 +9,7 @@
package org.gridgain.grid.kernal.processors.cache.query;
+import org.apache.ignite.spi.indexing.*;
import org.jetbrains.annotations.*;
import java.io.*;
@@ -34,7 +35,7 @@ public interface GridCacheSqlMetadata extends Externalizable {
* <p>
* By default, type name is equal to simple class name
* of stored object, but it can depend on implementation
- * of {@link org.apache.ignite.spi.indexing.IndexingSpi}.
+ * of {@link GridIndexingSpi}.
*
* @return Collection of available types.
*/
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java
index ccfadec..a080192 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java
@@ -16,12 +16,12 @@ import org.apache.ignite.marshaller.*;
import org.apache.ignite.marshaller.jdk.*;
import org.apache.ignite.marshaller.optimized.*;
import org.apache.ignite.resources.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.*;
import org.gridgain.grid.kernal.processors.cache.query.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.lang.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
@@ -199,7 +199,7 @@ public class GridCacheQueryJdbcTask extends ComputeTaskAdapter<byte[], byte[]> {
GridCacheQueryFuture<List<?>> fut = qry.execute(args.toArray());
- Collection<IndexingFieldMetadata> meta = ((GridCacheQueryMetadataAware)fut).metadata().get();
+ Collection<GridQueryFieldMetadata> meta = ((GridCacheQueryMetadataAware)fut).metadata().get();
if (meta == null) {
// Try to extract initial SQL exception.
@@ -220,7 +220,7 @@ public class GridCacheQueryJdbcTask extends ComputeTaskAdapter<byte[], byte[]> {
cols = new ArrayList<>(meta.size());
types = new ArrayList<>(meta.size());
- for (IndexingFieldMetadata desc : meta) {
+ for (GridQueryFieldMetadata desc : meta) {
tbls.add(desc.typeName());
cols.add(desc.fieldName().toUpperCase());
types.add(desc.fieldTypeName());
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldMetadata.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldMetadata.java
new file mode 100644
index 0000000..9799cda
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldMetadata.java
@@ -0,0 +1,46 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+import java.io.*;
+
+/**
+ * Query field descriptor. This descriptor is used to provide metadata
+ * about fields returned in query result.
+ */
+public interface GridQueryFieldMetadata extends Externalizable {
+ /**
+ * Gets schema name.
+ *
+ * @return Schema name.
+ */
+ public String schemaName();
+
+ /**
+ * Gets name of type to which this field belongs.
+ *
+ * @return Gets type name.
+ */
+ public String typeName();
+
+ /**
+ * Gets field name.
+ *
+ * @return Field name.
+ */
+ public String fieldName();
+
+ /**
+ * Gets field type name.
+ *
+ * @return Field type name.
+ */
+ public String fieldTypeName();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResult.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResult.java
new file mode 100644
index 0000000..ae2ab8a
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResult.java
@@ -0,0 +1,34 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+import org.apache.ignite.spi.*;
+
+import java.util.*;
+
+/**
+ * Field query result. It is composed of
+ * fields metadata and iterator over queried fields.
+ */
+public interface GridQueryFieldsResult {
+ /**
+ * Gets metadata for queried fields.
+ *
+ * @return Meta data for queried fields.
+ */
+ List<GridQueryFieldMetadata> metaData();
+
+ /**
+ * Gets iterator over queried fields.
+ *
+ * @return Iterator over queried fields.
+ */
+ IgniteSpiCloseableIterator<List<?>> iterator();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResultAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResultAdapter.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResultAdapter.java
new file mode 100644
index 0000000..cf5e855
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryFieldsResultAdapter.java
@@ -0,0 +1,49 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+import org.gridgain.grid.util.lang.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+/**
+ * Convenience adapter for {@link GridQueryFieldsResult}.
+ */
+public class GridQueryFieldsResultAdapter implements GridQueryFieldsResult {
+ /** Meta data. */
+ private final List<GridQueryFieldMetadata> metaData;
+
+ /** Result iterator. */
+ private final GridCloseableIterator<List<?>> it;
+
+ /**
+ * Creates query field result composed of field metadata and iterator
+ * over queried fields.
+ *
+ * @param metaData Meta data.
+ * @param it Result iterator.
+ */
+ public GridQueryFieldsResultAdapter(@Nullable List<GridQueryFieldMetadata> metaData,
+ GridCloseableIterator<List<?>> it) {
+ this.metaData = metaData != null ? Collections.unmodifiableList(metaData) : null;
+ this.it = it;
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<GridQueryFieldMetadata> metaData() {
+ return metaData;
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridCloseableIterator<List<?>> iterator() {
+ return it;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexDescriptor.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexDescriptor.java
new file mode 100644
index 0000000..a971123
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexDescriptor.java
@@ -0,0 +1,42 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+import java.util.*;
+
+/**
+ * Describes an index to be created for a certain type. It contains all necessary
+ * information about fields, order, uniqueness, and specified
+ * whether this is SQL or Text index.
+ * See also {@link GridQueryTypeDescriptor#indexes()}.
+ */
+public interface GridQueryIndexDescriptor {
+ /**
+ * Gets all fields to be indexed.
+ *
+ * @return Fields to be indexed.
+ */
+ public Collection<String> fields();
+
+ /**
+ * Specifies order of the index for each indexed field.
+ *
+ * @param field Field name.
+ * @return {@code True} if given field should be indexed in descending order.
+ */
+ public boolean descending(String field);
+
+ /**
+ * Gets index type.
+ *
+ * @return Type.
+ */
+ public GridQueryIndexType type();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexType.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexType.java
new file mode 100644
index 0000000..313b117
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexType.java
@@ -0,0 +1,24 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+/**
+ * Index types.
+ */
+public enum GridQueryIndexType {
+ /** Sorted SQL index. */
+ SORTED,
+
+ /** Spatial SQL index. */
+ GEO_SPATIAL,
+
+ /** Fulltext index. */
+ FULLTEXT
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexing.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexing.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexing.java
new file mode 100644
index 0000000..e22bfd4
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/query/GridQueryIndexing.java
@@ -0,0 +1,162 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query;
+
+import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.indexing.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.kernal.*;
+import org.gridgain.grid.util.lang.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+/**
+ * Abstraction for internal indexing implementation.
+ */
+public interface GridQueryIndexing {
+ /**
+ * Starts indexing.
+ *
+ * @param ctx Context.
+ * @throws GridException If failed.
+ */
+ public void start(GridKernalContext ctx) throws GridException;
+
+ /**
+ * Stops indexing.
+ *
+ * @throws GridException If failed.
+ */
+ public void stop() throws GridException;
+
+ /**
+ * Queries individual fields (generally used by JDBC drivers).
+ *
+ * @param spaceName Space name.
+ * @param qry Query.
+ * @param params Query parameters.
+ * @param filters Space name and key filters.
+ * @return Query result.
+ * @throws GridException If failed.
+ */
+ public <K, V> GridQueryFieldsResult queryFields(@Nullable String spaceName, String qry,
+ Collection<Object> params, GridIndexingQueryFilter filters) throws GridException;
+
+ /**
+ * Executes regular query.
+ *
+ * @param spaceName Space name.
+ * @param qry Query.
+ * @param params Query parameters.
+ * @param type Query return type.
+ * @param filters Space name and key filters.
+ * @return Queried rows.
+ * @throws GridException If failed.
+ */
+ public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> query(@Nullable String spaceName, String qry,
+ Collection<Object> params, GridQueryTypeDescriptor type, GridIndexingQueryFilter filters) throws GridException;
+
+ /**
+ * Executes text query.
+ *
+ * @param spaceName Space name.
+ * @param qry Text query.
+ * @param type Query return type.
+ * @param filters Space name and key filter.
+ * @return Queried rows.
+ * @throws GridException If failed.
+ */
+ public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryText(@Nullable String spaceName, String qry,
+ GridQueryTypeDescriptor type, GridIndexingQueryFilter filters) throws GridException;
+
+ /**
+ * Gets size of index for given type or -1 if it is a unknown type.
+ *
+ * @param spaceName Space name.
+ * @param desc Type descriptor.
+ * @param filters Filters.
+ * @return Objects number.
+ * @throws GridException If failed.
+ */
+ public long size(@Nullable String spaceName, GridQueryTypeDescriptor desc, GridIndexingQueryFilter filters)
+ throws GridException;
+
+ /**
+ * Registers type if it was not known before or updates it otherwise.
+ *
+ * @param spaceName Space name.
+ * @param desc Type descriptor.
+ * @throws GridException If failed.
+ * @return {@code True} if type was registered, {@code false} if for some reason it was rejected.
+ */
+ public boolean registerType(@Nullable String spaceName, GridQueryTypeDescriptor desc) throws GridException;
+
+ /**
+ * Unregisters type and removes all corresponding data.
+ *
+ * @param spaceName Space name.
+ * @param type Type descriptor.
+ * @throws GridException If failed.
+ */
+ public void unregisterType(@Nullable String spaceName, GridQueryTypeDescriptor type) throws GridException;
+
+ /**
+ * Updates index. Note that key is unique for space, so if space contains multiple indexes
+ * the key should be removed from indexes other than one being updated.
+ *
+ * @param spaceName Space name.
+ * @param type Value type.
+ * @param key Key.
+ * @param val Value.
+ * @param ver Version.
+ * @param expirationTime Expiration time or 0 if never expires.
+ * @throws GridException If failed.
+ */
+ public void store(@Nullable String spaceName, GridQueryTypeDescriptor type, Object key, Object val, byte[] ver,
+ long expirationTime) throws GridException;
+
+ /**
+ * Removes index entry by key.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @throws GridException If failed.
+ */
+ public void remove(@Nullable String spaceName, Object key) throws GridException;
+
+ /**
+ * Will be called when entry with given key is swapped.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @throws GridException If failed.
+ */
+ public void onSwap(@Nullable String spaceName, Object key) throws GridException;
+
+ /**
+ * Will be called when entry with given key is unswapped.
+ *
+ * @param spaceName Space name.
+ * @param key Key.
+ * @param val Value.
+ * @param valBytes Value bytes.
+ * @throws GridException If failed.
+ */
+ public void onUnswap(@Nullable String spaceName, Object key, Object val, byte[] valBytes) throws GridException;
+
+ /**
+ * Rebuilds all indexes of given type.
+ *
+ * @param spaceName Space name.
+ * @param type Type descriptor.
+ */
+ public void rebuildIndexes(@Nullable String spaceName, GridQueryTypeDescriptor type);
+}
[07/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOffheap.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOffheap.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOffheap.java
new file mode 100644
index 0000000..90fa24d
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOffheap.java
@@ -0,0 +1,346 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.ignite.spi.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+import org.h2.store.*;
+import org.h2.value.*;
+import org.jetbrains.annotations.*;
+
+import java.util.concurrent.locks.*;
+
+/**
+ * Offheap row.
+ */
+public class GridH2KeyValueRowOffheap extends GridH2AbstractKeyValueRow {
+ /** */
+ private static final GridStripedLock lock;
+
+ /**
+ * Init locks.
+ */
+ static {
+ int cpus = Runtime.getRuntime().availableProcessors();
+
+ lock = new GridStripedLock(cpus * cpus * 8);
+ }
+
+ /** */
+ private static final int OFFSET_KEY_SIZE = 4; // 4 after ref cnt int
+
+ /** */
+ private static final int OFFSET_VALUE_REF = OFFSET_KEY_SIZE + 4; // 8
+
+ /** */
+ private static final int OFFSET_EXPIRATION = OFFSET_VALUE_REF + 8; // 16
+
+ /** */
+ private static final int OFFSET_KEY = OFFSET_EXPIRATION + 8; // 24
+
+ /** */
+ private static final int OFFSET_VALUE = 4; // 4 on separate page after val size int
+
+ /** */
+ private static final Data SIZE_CALCULATOR = Data.create(null, null);
+
+ /** */
+ @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
+ private long ptr;
+
+ /**
+ * @param desc Row descriptor.
+ * @param ptr Pointer.
+ */
+ public GridH2KeyValueRowOffheap(GridH2RowDescriptor desc, long ptr) {
+ super(desc);
+
+ assert ptr > 0 : ptr;
+
+ this.ptr = ptr;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param desc Row descriptor.
+ * @param key Key.
+ * @param keyType Key type.
+ * @param val Value.
+ * @param valType Value type.
+ * @param expirationTime Expiration time.
+ * @throws IgniteSpiException If failed.
+ */
+ public GridH2KeyValueRowOffheap(GridH2RowDescriptor desc, Object key, int keyType, @Nullable Object val, int valType,
+ long expirationTime) throws IgniteSpiException {
+ super(desc, key, keyType, val, valType, expirationTime);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long expirationTime() {
+ if (expirationTime == 0) {
+ long p = ptr;
+
+ assert p > 0 : p;
+
+ // We don't need any synchronization or volatility here because we publish via
+ // volatile write to tree node.
+ expirationTime = desc.memory().readLong(p + OFFSET_EXPIRATION);
+ }
+
+ return expirationTime;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void cache() {
+ desc.cache(this);
+ }
+
+ /**
+ * @param ptr Pointer to get lock for.
+ * @return Locked lock, must be released in {@code finally} block.
+ */
+ @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+ private static Lock lock(long ptr) {
+ assert (ptr & 7) == 0 : ptr; // Unsafe allocated pointers aligned.
+
+ Lock l = lock.getLock(ptr >>> 3);
+
+ l.lock();
+
+ return l;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+ @Override protected Value getOffheapValue(int col) {
+ GridUnsafeMemory mem = desc.memory();
+
+ long p = ptr;
+
+ assert p > 0 : p;
+
+ byte[] bytes = null;
+
+ if (col == KEY_COL) {
+ int size = mem.readInt(p + OFFSET_KEY_SIZE);
+
+ assert size > 0 : size;
+
+ bytes = mem.readBytes(p + OFFSET_KEY, size);
+ }
+ else if (col == VAL_COL) {
+ Lock l = lock(p);
+
+ desc.guard().begin();
+
+ try {
+ long valPtr = mem.readLongVolatile(p + OFFSET_VALUE_REF);
+
+ if (valPtr == 0) // Value was evicted.
+ return null;
+
+ int size = mem.readInt(valPtr);
+
+ assert size > 0 : size;
+
+ bytes = mem.readBytes(valPtr + OFFSET_VALUE, size);
+ }
+ finally {
+ desc.guard().end();
+
+ l.unlock();
+ }
+ }
+ else
+ assert false : col;
+
+ Data data = Data.create(null, bytes);
+
+ return data.readValue();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long pointer() {
+ long p = ptr;
+
+ assert p > 0: p;
+
+ return p;
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void onSwap() throws GridException {
+ Lock l = lock(ptr);
+
+ try {
+ final long p = ptr + OFFSET_VALUE_REF;
+
+ final GridUnsafeMemory mem = desc.memory();
+
+ final long valPtr = mem.readLongVolatile(p);
+
+ assert valPtr > 0: valPtr;
+
+ desc.guard().finalizeLater(new Runnable() {
+ @Override public void run() {
+ mem.casLong(p, valPtr, 0); // If it was unswapped concurrently we will not update.
+
+ mem.release(valPtr, mem.readInt(valPtr) + OFFSET_VALUE);
+ }
+ });
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod")
+ @Override protected Value updateWeakValue(Value exp, Value upd) {
+ return exp;
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void onUnswap(Object val) throws GridException {
+ super.onUnswap(val);
+
+ Value v = getValue(VAL_COL);
+
+ byte[] bytes = new byte[SIZE_CALCULATOR.getValueLen(v)];
+
+ Data data = Data.create(null, bytes);
+
+ data.writeValue(v);
+
+ long p = ptr;
+
+ assert p > 0 : p;
+
+ Lock l = lock(p);
+
+ try {
+ GridUnsafeMemory mem = desc.memory();
+
+ long valPtr = mem.allocate(bytes.length + OFFSET_VALUE);
+
+ mem.writeInt(valPtr, bytes.length);
+ mem.writeBytes(valPtr + OFFSET_VALUE, bytes);
+
+ mem.writeLongVolatile(p + OFFSET_VALUE_REF, valPtr);
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected synchronized Value syncValue() {
+ Value v = super.syncValue();
+
+ if (v != null)
+ return v;
+
+ return getOffheapValue(VAL_COL);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext"})
+ @Override public void incrementRefCount() {
+ long p = ptr;
+
+ GridUnsafeMemory mem = desc.memory();
+
+ if (p == 0) { // Serialize data to offheap memory.
+ Value key = getValue(KEY_COL);
+ Value val = getValue(VAL_COL);
+
+ assert key != null;
+ assert val != null;
+
+ Data data = Data.create(null, new byte[SIZE_CALCULATOR.getValueLen(key)]);
+
+ data.writeValue(key);
+
+ int keySize = data.length();
+
+ p = mem.allocate(keySize + OFFSET_KEY);
+
+ // We don't need any synchronization or volatility here because we publish via
+ // volatile write to tree node.
+ mem.writeInt(p, 1);
+ mem.writeLong(p + OFFSET_EXPIRATION, expirationTime);
+ mem.writeInt(p + OFFSET_KEY_SIZE, keySize);
+ mem.writeBytes(p + OFFSET_KEY, data.getBytes(), 0, keySize);
+
+ data = Data.create(null, new byte[SIZE_CALCULATOR.getValueLen(val)]);
+
+ data.writeValue(val);
+
+ int valSize = data.length();
+
+ long valPtr = mem.allocate(valSize + OFFSET_VALUE);
+
+ mem.writeInt(valPtr, valSize);
+ mem.writeBytes(valPtr + OFFSET_VALUE, data.getBytes(), 0, valSize);
+
+ mem.writeLongVolatile(p + OFFSET_VALUE_REF, valPtr);
+
+ ptr = p;
+
+ desc.cache(this);
+ }
+ else {
+ for (;;) {
+ int cnt = mem.readIntVolatile(p);
+
+ assert cnt > 0 : cnt;
+
+ if (mem.casInt(p, cnt, cnt + 1))
+ break;
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void decrementRefCount() {
+ long p = ptr;
+
+ assert p > 0 : p;
+
+ GridUnsafeMemory mem = desc.memory();
+
+ for (;;) {
+ int cnt = mem.readIntVolatile(p);
+
+ assert cnt > 0 : cnt;
+
+ if (cnt == 1)
+ break;
+
+ if (mem.casInt(p, cnt, cnt - 1))
+ return;
+ }
+
+ desc.uncache(p);
+
+ // Deallocate off-heap memory.
+ long valPtr = mem.readLongVolatile(p + OFFSET_VALUE_REF);
+
+ assert valPtr >= 0 : valPtr;
+
+ if (valPtr != 0)
+ mem.release(valPtr, mem.readInt(valPtr) + OFFSET_VALUE);
+
+ mem.release(p, mem.readInt(p + OFFSET_KEY_SIZE) + OFFSET_KEY);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
new file mode 100644
index 0000000..22cd94e
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2KeyValueRowOnheap.java
@@ -0,0 +1,46 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+
+import org.apache.ignite.spi.*;
+import org.h2.value.*;
+import org.jetbrains.annotations.*;
+
+/**
+ * Onheap row.
+ */
+public class GridH2KeyValueRowOnheap extends GridH2AbstractKeyValueRow {
+ /**
+ * Constructor.
+ *
+ * @param desc Row descriptor.
+ * @param key Key.
+ * @param keyType Key type.
+ * @param val Value.
+ * @param valType Value type.
+ * @param expirationTime Expiration time.
+ * @throws IgniteSpiException If failed.
+ */
+ public GridH2KeyValueRowOnheap(GridH2RowDescriptor desc, Object key, int keyType, @Nullable Object val, int valType,
+ long expirationTime) throws IgniteSpiException {
+ super(desc, key, keyType, val, valType, expirationTime);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void cache() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Value getOffheapValue(int col) {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Row.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Row.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Row.java
new file mode 100644
index 0000000..3a88938
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Row.java
@@ -0,0 +1,40 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.h2.result.*;
+import org.h2.value.*;
+
+/**
+ * Row with locking support needed for unique key conflicts resolution.
+ */
+public class GridH2Row extends Row implements GridSearchRowPointer {
+ /**
+ * @param data Column values.
+ */
+ public GridH2Row(Value... data) {
+ super(data, MEMORY_CALCULATE);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long pointer() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void incrementRefCount() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void decrementRefCount() {
+ throw new IllegalStateException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2RowDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2RowDescriptor.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2RowDescriptor.java
new file mode 100644
index 0000000..685a128
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2RowDescriptor.java
@@ -0,0 +1,102 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.gridgain.grid.*;
+import org.gridgain.grid.kernal.processors.query.h2.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+import org.jetbrains.annotations.*;
+
+/**
+ * Row descriptor.
+ */
+public interface GridH2RowDescriptor extends GridOffHeapSmartPointerFactory<GridH2KeyValueRowOffheap> {
+ /**
+ * @return Owner.
+ */
+ public GridH2Indexing owner();
+
+ /**
+ * Creates new row.
+ *
+ * @param key Key.
+ * @param val Value.
+ * @param expirationTime Expiration time in millis.
+ * @return Row.
+ * @throws GridException If failed.
+ */
+ public GridH2AbstractKeyValueRow createRow(Object key, @Nullable Object val, long expirationTime)
+ throws GridException;
+
+ /**
+ * @param key Cache key.
+ * @return Value.
+ * @throws GridException If failed.
+ */
+ public Object readFromSwap(Object key) throws GridException;
+
+ /**
+ * @return Value type.
+ */
+ public int valueType();
+
+ /**
+ * @return {@code true} If we need to store {@code toString()} of value.
+ */
+ public boolean valueToString();
+
+ /**
+ * @return Total fields count.
+ */
+ public int fieldsCount();
+
+ /**
+ * Gets value type for column index.
+ *
+ * @param col Column index.
+ * @return Value type.
+ */
+ public int fieldType(int col);
+
+ /**
+ * Gets column value by column index.
+ *
+ * @param obj Object to extract value from.
+ * @param col Column index.
+ * @return Column value.
+ */
+ public Object columnValue(Object obj, int col);
+
+ /**
+ * @param col Column index.
+ * @return {@code True} if column relates to key, false if it relates to value.
+ */
+ public boolean isKeyColumn(int col);
+
+ /**
+ * @return Unsafe memory.
+ */
+ public GridUnsafeMemory memory();
+
+ /**
+ * @param row Deserialized offheap row to cache in heap.
+ */
+ public void cache(GridH2KeyValueRowOffheap row);
+
+ /**
+ * @param ptr Offheap pointer to remove from cache.
+ */
+ public void uncache(long ptr);
+
+ /**
+ * @return Guard.
+ */
+ public GridUnsafeGuard guard();
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2SpatialIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2SpatialIndex.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2SpatialIndex.java
new file mode 100644
index 0000000..20aab15
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2SpatialIndex.java
@@ -0,0 +1,318 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import com.vividsolutions.jts.geom.*;
+import org.h2.engine.*;
+import org.h2.index.*;
+import org.h2.index.Cursor;
+import org.h2.message.*;
+import org.h2.mvstore.*;
+import org.h2.mvstore.rtree.*;
+import org.h2.result.*;
+import org.h2.table.*;
+import org.h2.value.*;
+
+import java.util.*;
+import java.util.concurrent.locks.*;
+
+/**
+ * Spatial index.
+ */
+public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex {
+ /** */
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ /** */
+ private volatile long rowCnt;
+
+ /** */
+ private long rowIds;
+
+ /** */
+ private boolean closed;
+
+ /** */
+ private final MVRTreeMap<Long> treeMap;
+
+ /** */
+ private final Map<Long, GridH2Row> idToRow = new HashMap<>();
+
+ /** */
+ private final Map<Value, Long> keyToId = new HashMap<>();
+
+ /** */
+ private final MVStore store;
+
+ /**
+ * @param tbl Table.
+ * @param idxName Index name.
+ * @param cols Columns.
+ * @param keyCol Key column.
+ * @param valCol Value column.
+ */
+ public GridH2SpatialIndex(Table tbl, String idxName, IndexColumn[] cols, int keyCol, int valCol) {
+ super(keyCol, valCol);
+
+ if (cols.length > 1)
+ throw DbException.getUnsupportedException("can only do one column");
+
+ if ((cols[0].sortType & SortOrder.DESCENDING) != 0)
+ throw DbException.getUnsupportedException("cannot do descending");
+
+ if ((cols[0].sortType & SortOrder.NULLS_FIRST) != 0)
+ throw DbException.getUnsupportedException("cannot do nulls first");
+
+ if ((cols[0].sortType & SortOrder.NULLS_LAST) != 0)
+ throw DbException.getUnsupportedException("cannot do nulls last");
+
+ initBaseIndex(tbl, 0, idxName, cols, IndexType.createNonUnique(false, false, true));
+
+ table = tbl;
+
+ if (cols[0].column.getType() != Value.GEOMETRY) {
+ throw DbException.getUnsupportedException("spatial index on non-geometry column, " +
+ cols[0].column.getCreateSQL());
+ }
+
+ // Index in memory
+ store = MVStore.open(null);
+ treeMap = store.openMap("spatialIndex", new MVRTreeMap.Builder<Long>());
+ }
+
+ /**
+ * Check closed.
+ */
+ private void checkClosed() {
+ if (closed)
+ throw DbException.throwInternalError();
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2Row put(GridH2Row row) {
+ Lock l = lock.writeLock();
+
+ l.lock();
+
+ try {
+ checkClosed();
+
+ Value key = row.getValue(keyCol);
+
+ assert key != null;
+
+ Long rowId = keyToId.get(key);
+
+ if (rowId != null) {
+ Long oldRowId = treeMap.remove(getEnvelope(idToRow.get(rowId), rowId));
+
+ assert rowId.equals(oldRowId);
+ }
+ else {
+ rowId = ++rowIds;
+
+ keyToId.put(key, rowId);
+ }
+
+ GridH2Row old = idToRow.put(rowId, row);
+
+ treeMap.put(getEnvelope(row, rowId), rowId);
+
+ if (old == null)
+ rowCnt++; // No replace.
+
+ return old;
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /**
+ * @param row Row.
+ * @param rowId Row id.
+ * @return Envelope.
+ */
+ private SpatialKey getEnvelope(SearchRow row, long rowId) {
+ Value v = row.getValue(columnIds[0]);
+ Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometry();
+ Envelope env = g.getEnvelopeInternal();
+ return new SpatialKey(rowId,
+ (float) env.getMinX(), (float) env.getMaxX(),
+ (float) env.getMinY(), (float) env.getMaxY());
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2Row remove(SearchRow row) {
+ Lock l = lock.writeLock();
+
+ l.lock();
+
+ try {
+ checkClosed();
+
+ Value key = row.getValue(keyCol);
+
+ assert key != null;
+
+ Long rowId = keyToId.remove(key);
+
+ assert rowId != null;
+
+ GridH2Row oldRow = idToRow.remove(rowId);
+
+ assert oldRow != null;
+
+ if (!treeMap.remove(getEnvelope(row, rowId), rowId))
+ throw DbException.throwInternalError("row not found");
+
+ rowCnt--;
+
+ return oldRow;
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close(Session ses) {
+ Lock l = lock.writeLock();
+
+ l.lock();
+
+ try {
+ closed = true;
+
+ store.close();
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long getCostRangeIndex(int[] masks, long rowCnt, TableFilter filter, SortOrder sortOrder) {
+ rowCnt += Constants.COST_ROW_OFFSET;
+ long cost = rowCnt;
+ long rows = rowCnt;
+
+ if (masks == null)
+ return cost;
+
+ for (Column column : columns) {
+ int idx = column.getColumnId();
+ int mask = masks[idx];
+ if ((mask & IndexCondition.SPATIAL_INTERSECTS) != 0) {
+ cost = 3 + rows / 4;
+
+ break;
+ }
+ }
+
+ return cost;
+ }
+
+ /** {@inheritDoc} */
+ @Override public double getCost(Session ses, int[] masks, TableFilter filter, SortOrder sortOrder) {
+ return getCostRangeIndex(masks, rowCnt, filter, sortOrder);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor find(Session ses, SearchRow first, SearchRow last) {
+ Lock l = lock.readLock();
+
+ l.lock();
+
+ try {
+ checkClosed();
+
+ return new GridH2Cursor(rowIterator(treeMap.keySet().iterator()));
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canGetFirstOrLast() {
+ return true;
+ }
+
+ /**
+ * @param i Spatial key iterator.
+ * @return Iterator over rows.
+ */
+ private Iterator<GridH2Row> rowIterator(Iterator<SpatialKey> i) {
+ if (!i.hasNext())
+ return Collections.emptyIterator();
+
+ List<GridH2Row> rows = new ArrayList<>();
+
+ do {
+ GridH2Row row = idToRow.get(i.next().getId());
+
+ assert row != null;
+
+ rows.add(row);
+ }
+ while (i.hasNext());
+
+ return filter(rows.iterator());
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor findFirstOrLast(Session ses, boolean first) {
+ Lock l = lock.readLock();
+
+ l.lock();
+
+ try {
+ checkClosed();
+
+ if (!first)
+ throw DbException.throwInternalError("Spatial Index can only be fetch by ascending order");
+
+ Iterator<GridH2Row> iter = rowIterator(treeMap.keySet().iterator());
+
+ return new SingleRowCursor(iter.hasNext() ? iter.next() : null);
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCount(Session ses) {
+ return rowCnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ return rowCnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor findByGeometry(TableFilter filter, SearchRow intersection) {
+ Lock l = lock.readLock();
+
+ l.lock();
+
+ try {
+ if (intersection == null)
+ return find(filter.getSession(), null, null);
+
+ return new GridH2Cursor(rowIterator(treeMap.findIntersectingKeys(getEnvelope(intersection, 0))));
+ }
+ finally {
+ l.unlock();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Table.java
new file mode 100644
index 0000000..e1c91fc
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Table.java
@@ -0,0 +1,889 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+
+import org.gridgain.grid.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+import org.h2.api.*;
+import org.h2.command.ddl.*;
+import org.h2.engine.*;
+import org.h2.index.*;
+import org.h2.message.*;
+import org.h2.result.*;
+import org.h2.schema.*;
+import org.h2.table.*;
+import org.jdk8.backport.*;
+import org.jetbrains.annotations.*;
+
+import java.sql.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+
+/**
+ * H2 Table implementation.
+ */
+public class GridH2Table extends TableBase {
+ /** */
+ private final String spaceName;
+
+ /** */
+ private final GridH2RowDescriptor desc;
+
+ /** */
+ private final ArrayList<Index> idxs;
+
+ /** */
+ private final ReadWriteLock lock;
+
+ /** */
+ private final Set<Session> sessions = Collections.newSetFromMap(new ConcurrentHashMap8<Session, Boolean>());
+
+ /** */
+ private volatile Object[] actualSnapshot;
+
+ /**
+ * Creates table.
+ *
+ * @param createTblData Table description.
+ * @param desc Row descriptor.
+ * @param idxsFactory Indexes factory.
+ * @param spaceName Space name.
+ */
+ public GridH2Table(CreateTableData createTblData, @Nullable GridH2RowDescriptor desc, IndexesFactory idxsFactory,
+ @Nullable String spaceName) {
+ super(createTblData);
+
+ assert idxsFactory != null;
+
+ this.desc = desc;
+ this.spaceName = spaceName;
+
+ idxs = idxsFactory.createIndexes(this);
+
+ assert idxs != null;
+ assert idxs.size() >= 1;
+
+ lock = new ReentrantReadWriteLock();
+
+ // Add scan index at 0 which is required by H2.
+ idxs.add(0, new ScanIndex(index(0)));
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDiskSpaceUsed() {
+ return 0;
+ }
+
+ /**
+ * @return Row descriptor.
+ */
+ public GridH2RowDescriptor rowDescriptor() {
+ return desc;
+ }
+
+ /**
+ * Should be called when entry is swapped.
+ *
+ * @param key Entry key.
+ * @return {@code true} If row was found.
+ * @throws GridException If failed.
+ */
+ public boolean onSwap(Object key) throws GridException {
+ return onSwapUnswap(key, null);
+ }
+
+ /**
+ * Should be called when entry is unswapped.
+ *
+ * @param key Key.
+ * @param val Value.
+ * @return {@code true} If row was found.
+ * @throws GridException If failed.
+ */
+ public boolean onUnswap(Object key, Object val) throws GridException {
+ assert val != null : "Key=" + key;
+
+ return onSwapUnswap(key, val);
+ }
+
+ /**
+ * Swaps or unswaps row.
+ *
+ * @param key Key.
+ * @param val Value for promote or {@code null} if we have to swap.
+ * @return {@code true} if row was found and swapped/unswapped.
+ * @throws GridException If failed.
+ */
+ @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+ private boolean onSwapUnswap(Object key, @Nullable Object val) throws GridException {
+ assert key != null;
+
+ GridH2TreeIndex pk = pk();
+
+ assert desc != null;
+
+ GridH2AbstractKeyValueRow row = desc.createRow(key, null, 0); // Create search row.
+
+ GridUnsafeMemory mem = desc.memory();
+
+ lock.readLock().lock();
+
+ if (mem != null)
+ desc.guard().begin();
+
+ try {
+ row = pk.findOne(row);
+
+ if (row == null)
+ return false;
+
+ if (val == null)
+ row.onSwap();
+ else
+ row.onUnswap(val);
+
+ return true;
+ }
+ finally {
+ lock.readLock().unlock();
+
+ if (mem != null)
+ desc.guard().end();
+ }
+ }
+
+ /**
+ * @return Space name.
+ */
+ @Nullable String spaceName() {
+ return spaceName;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings({"LockAcquiredButNotSafelyReleased", "SynchronizationOnLocalVariableOrMethodParameter", "unchecked"})
+ @Override public void lock(@Nullable final Session ses, boolean exclusive, boolean force) {
+ if (ses != null) {
+ if (!sessions.add(ses))
+ return;
+
+ synchronized (ses) {
+ ses.addLock(this);
+ }
+ }
+
+ Object[] snapshot;
+
+ for (long waitTime = 100;; waitTime *= 2) { // Increase wait time to avoid starvation.
+ snapshot = actualSnapshot;
+
+ if (snapshot != null) {
+ // Reuse existing snapshot without locking.
+ for (int i = 1, len = idxs.size(); i < len; i++)
+ index(i).takeSnapshot(snapshot[i - 1]);
+
+ return;
+ }
+
+ try {
+ if (lock.writeLock().tryLock(waitTime, TimeUnit.MILLISECONDS))
+ break;
+ }
+ catch (InterruptedException e) {
+ throw new GridRuntimeException("Thread got interrupted while trying to acquire index lock.", e);
+ }
+ }
+
+ boolean snapshoted = false;
+
+ try {
+ snapshot = actualSnapshot; // Try again inside of the lock.
+
+ if (snapshot == null) {
+ snapshot = takeIndexesSnapshot();
+
+ if (desc == null || desc.memory() == null) // This optimization is disabled for off-heap index.
+ actualSnapshot = snapshot;
+
+ snapshoted = true;
+ }
+ }
+ finally {
+ lock.writeLock().unlock();
+ }
+
+ if (!snapshoted) {
+ for (int i = 1, len = idxs.size(); i < len; i++)
+ index(i).takeSnapshot(snapshot[i - 1]);
+ }
+ }
+
+ /**
+ * Must be called inside of write lock because when using multiple indexes we have to ensure that all of them have
+ * the same contents at snapshot taking time.
+ *
+ * @return New indexes data snapshot.
+ */
+ @SuppressWarnings("unchecked")
+ private Object[] takeIndexesSnapshot() {
+ int len = idxs.size();
+
+ Object[] snapshot = new ConcurrentNavigableMap[len - 1];
+
+ for (int i = 1; i < len; i++) { // Take snapshots on all except first which is scan.
+ Object s = index(i).takeSnapshot(null);
+
+ snapshot[i - 1] = s;
+ }
+
+ return snapshot;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close(Session ses) {
+ assert !sessions.contains(ses);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void unlock(@Nullable Session ses) {
+ if (ses != null) {
+ boolean res = sessions.remove(ses);
+
+ assert res;
+ }
+
+ for (int i = 1, len = idxs.size(); i < len; i++) // Release snapshots on all except first which is scan.
+ index(i).releaseSnapshot();
+ }
+
+ /**
+ * Closes table and releases resources.
+ */
+ public void close() {
+ Lock l = lock.writeLock();
+
+ l.lock();
+
+ try {
+ for (int i = 1, len = idxs.size(); i < len; i++)
+ index(i).close(null);
+ }
+ finally {
+ l.unlock();
+ }
+ }
+
+ /**
+ * Updates table for given key. If value is null then row with given key will be removed from table,
+ * otherwise value and expiration time will be updated or new row will be added.
+ *
+ * @param key Key.
+ * @param val Value.
+ * @param expirationTime Expiration time.
+ * @return {@code True} if operation succeeded.
+ * @throws GridException If failed.
+ */
+ public boolean update(Object key, @Nullable Object val, long expirationTime) throws GridException {
+ assert desc != null;
+
+ GridH2Row row = desc.createRow(key, val, expirationTime);
+
+ return doUpdate(row, val == null);
+ }
+
+ /**
+ * Gets index by index.
+ *
+ * @param idx Index in list.
+ * @return Index.
+ */
+ private GridH2IndexBase index(int idx) {
+ return (GridH2IndexBase)idxs.get(idx);
+ }
+
+ /**
+ * Gets primary key.
+ *
+ * @return Primary key.
+ */
+ private GridH2TreeIndex pk() {
+ return (GridH2TreeIndex)idxs.get(1);
+ }
+
+ /**
+ * For testing only.
+ *
+ * @param row Row.
+ * @param del If given row should be deleted from table.
+ * @return {@code True} if operation succeeded.
+ * @throws GridException If failed.
+ */
+ @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+ boolean doUpdate(GridH2Row row, boolean del) throws GridException {
+ // Here we assume that each key can't be updated concurrently and case when different indexes
+ // getting updated from different threads with different rows with the same key is impossible.
+ GridUnsafeMemory mem = desc == null ? null : desc.memory();
+
+ lock.readLock().lock();
+
+ if (mem != null)
+ desc.guard().begin();
+
+ try {
+ GridH2TreeIndex pk = pk();
+
+ if (!del) {
+ GridH2Row old = pk.put(row); // Put to PK.
+
+ int len = idxs.size();
+
+ int i = 1;
+
+ // Put row if absent to all indexes sequentially.
+ // Start from 2 because 0 - Scan (don't need to update), 1 - PK (already updated).
+ while (++i < len) {
+ GridH2IndexBase idx = index(i);
+
+ assert !idx.getIndexType().isUnique() : "Unique indexes are not supported.";
+
+ GridH2Row old2 = idx.put(row);
+
+ if (old2 != null) { // Row was replaced in index.
+ if (!eq(pk, old2, old))
+ throw new IllegalStateException("Row conflict should never happen, unique indexes are " +
+ "not supported.");
+ }
+ else if (old != null) // Row was not replaced, need to remove manually.
+ idx.remove(old);
+ }
+ }
+ else {
+ // index(1) is PK, get full row from there (search row here contains only key but no other columns).
+ row = pk.remove(row);
+
+ if (row != null) {
+ // Remove row from all indexes.
+ // Start from 2 because 0 - Scan (don't need to update), 1 - PK (already updated).
+ for (int i = 2, len = idxs.size(); i < len; i++) {
+ Row res = index(i).remove(row);
+
+ assert eq(pk, res, row): "\n" + row + "\n" + res;
+ }
+ }
+ else
+ return false;
+ }
+
+ // The snapshot is not actual after update.
+ actualSnapshot = null;
+
+ return true;
+ }
+ finally {
+ lock.readLock().unlock();
+
+ if (mem != null)
+ desc.guard().end();
+ }
+ }
+
+ /**
+ * Check row equality.
+ *
+ * @param pk Primary key index.
+ * @param r1 First row.
+ * @param r2 Second row.
+ * @return {@code true} if rows are the same.
+ */
+ private static boolean eq(Index pk, SearchRow r1, SearchRow r2) {
+ return r1 == r2 || (r1 != null && r2 != null && pk.compareRows(r1, r2) == 0);
+ }
+
+ /**
+ * For testing only.
+ *
+ * @return Indexes.
+ */
+ ArrayList<GridH2IndexBase> indexes() {
+ ArrayList<GridH2IndexBase> res = new ArrayList<>(idxs.size() - 1);
+
+ for (int i = 1, len = idxs.size(); i < len ; i++)
+ res.add(index(i));
+
+ return res;
+ }
+
+ /**
+ * Rebuilds all indexes of this table.
+ */
+ public void rebuildIndexes() {
+ GridUnsafeMemory memory = desc == null ? null : desc.memory();
+
+ lock.writeLock().lock();
+
+ try {
+ if (memory == null && actualSnapshot == null)
+ actualSnapshot = takeIndexesSnapshot(); // Allow read access while we are rebuilding indexes.
+
+ for (int i = 1, len = idxs.size(); i < len; i++) {
+ GridH2IndexBase newIdx = index(i).rebuild();
+
+ idxs.set(i, newIdx);
+
+ if (i == 1) // ScanIndex at 0 and actualSnapshot can contain references to old indexes, reset them.
+ idxs.set(0, new ScanIndex(newIdx));
+ }
+ }
+ catch (InterruptedException ignored) {
+ // No-op.
+ }
+ finally {
+ lock.writeLock().unlock();
+
+ actualSnapshot = null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public Index addIndex(Session ses, String s, int i, IndexColumn[] idxCols, IndexType idxType,
+ boolean b, String s1) {
+ throw DbException.getUnsupportedException("addIndex");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void removeRow(Session ses, Row row) {
+ throw DbException.getUnsupportedException("removeRow");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void truncate(Session ses) {
+ throw DbException.getUnsupportedException("truncate");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void addRow(Session ses, Row row) {
+ throw DbException.getUnsupportedException("addRow");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void checkSupportAlter() {
+ throw DbException.getUnsupportedException("alter");
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getTableType() {
+ return EXTERNAL_TABLE_ENGINE;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Index getScanIndex(Session ses) {
+ return getIndexes().get(0); // Scan must be always first index.
+ }
+
+ /** {@inheritDoc} */
+ @Override public Index getUniqueIndex() {
+ return getIndexes().get(1); // PK index is always second.
+ }
+
+ /** {@inheritDoc} */
+ @Override public ArrayList<Index> getIndexes() {
+ return idxs;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isLockedExclusively() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isLockedExclusivelyBy(Session ses) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getMaxDataModificationId() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isDeterministic() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canGetRowCount() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canDrop() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCount(@Nullable Session ses) {
+ return getUniqueIndex().getRowCount(ses);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ return getUniqueIndex().getRowCountApproximation();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void checkRename() {
+ throw DbException.getUnsupportedException("rename");
+ }
+
+ /**
+ * Creates index column for table.
+ *
+ * @param col Column index.
+ * @param sorting Sorting order {@link SortOrder}
+ * @return Created index column.
+ */
+ public IndexColumn indexColumn(int col, int sorting) {
+ IndexColumn res = new IndexColumn();
+
+ res.column = getColumn(col);
+ res.columnName = res.column.getName();
+ res.sortType = sorting;
+
+ return res;
+ }
+
+ /**
+ * H2 Table engine.
+ */
+ @SuppressWarnings({"PublicInnerClass", "FieldAccessedSynchronizedAndUnsynchronized"})
+ public static class Engine implements TableEngine {
+ /** */
+ private static GridH2RowDescriptor rowDesc;
+
+ /** */
+ private static IndexesFactory idxsFactory;
+
+ /** */
+ private static GridH2Table resTbl;
+
+ /** */
+ private static String spaceName;
+
+ /** {@inheritDoc} */
+ @Override public TableBase createTable(CreateTableData createTblData) {
+ resTbl = new GridH2Table(createTblData, rowDesc, idxsFactory, spaceName);
+
+ return resTbl;
+ }
+
+ /**
+ * Creates table using given connection, DDL clause for given type descriptor and list of indexes.
+ *
+ * @param conn Connection.
+ * @param sql DDL clause.
+ * @param desc Row descriptor.
+ * @param factory Indexes factory.
+ * @param space Space name.
+ * @throws SQLException If failed.
+ * @return Created table.
+ */
+ public static synchronized GridH2Table createTable(Connection conn, String sql,
+ @Nullable GridH2RowDescriptor desc, IndexesFactory factory, String space)
+ throws SQLException {
+ rowDesc = desc;
+ idxsFactory = factory;
+ spaceName = space;
+
+ try {
+ try (Statement s = conn.createStatement()) {
+ s.execute(sql + " engine \"" + Engine.class.getName() + "\"");
+ }
+
+ return resTbl;
+ }
+ finally {
+ resTbl = null;
+ idxsFactory = null;
+ rowDesc = null;
+ }
+ }
+ }
+
+ /**
+ * Type which can create indexes list for given table.
+ */
+ @SuppressWarnings({"PackageVisibleInnerClass", "PublicInnerClass"})
+ public static interface IndexesFactory {
+ /**
+ * Create list of indexes. First must be primary key, after that all unique indexes and
+ * only then non-unique indexes.
+ * All indexes must be subtypes of {@link GridH2TreeIndex}.
+ *
+ * @param tbl Table to create indexes for.
+ * @return List of indexes.
+ */
+ ArrayList<Index> createIndexes(GridH2Table tbl);
+ }
+
+ /**
+ * Wrapper type for primary key.
+ */
+ @SuppressWarnings("PackageVisibleInnerClass")
+ static class ScanIndex implements Index {
+ /** */
+ static final String SCAN_INDEX_NAME_SUFFIX = "__SCAN_";
+
+ /** */
+ private static final IndexType TYPE = IndexType.createScan(false);
+
+ /** */
+ private final GridH2IndexBase delegate;
+
+ /**
+ * Constructor.
+ *
+ * @param delegate Index delegate to.
+ */
+ private ScanIndex(GridH2IndexBase delegate) {
+ this.delegate = delegate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDiskSpaceUsed() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void add(Session ses, Row row) {
+ delegate.add(ses, row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canFindNext() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canGetFirstOrLast() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canScan() {
+ return delegate.canScan();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close(Session ses) {
+ delegate.close(ses);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void commit(int operation, Row row) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compareRows(SearchRow rowData, SearchRow compare) {
+ return delegate.compareRows(rowData, compare);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor find(TableFilter filter, SearchRow first, SearchRow last) {
+ return find(filter.getSession(), first, last);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor find(Session ses, SearchRow first, SearchRow last) {
+ return delegate.find(ses, null, null);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor findFirstOrLast(Session ses, boolean first) {
+ throw DbException.getUnsupportedException("SCAN");
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor findNext(Session ses, SearchRow higherThan, SearchRow last) {
+ throw DbException.throwInternalError();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getColumnIndex(Column col) {
+ return -1;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Column[] getColumns() {
+ return delegate.getColumns();
+ }
+
+ /** {@inheritDoc} */
+ @Override public double getCost(Session ses, int[] masks, TableFilter tblFilter, SortOrder sortOrder) {
+ return getRowCountApproximation() + Constants.COST_ROW_OFFSET;
+ }
+
+ /** {@inheritDoc} */
+ @Override public IndexColumn[] getIndexColumns() {
+ return delegate.getIndexColumns();
+ }
+
+ /** {@inheritDoc} */
+ @Override public IndexType getIndexType() {
+ return TYPE;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getPlanSQL() {
+ return delegate.getTable().getSQL() + "." + SCAN_INDEX_NAME_SUFFIX;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Row getRow(Session ses, long key) {
+ return delegate.getRow(ses, key);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCount(Session ses) {
+ return delegate.getRowCount(ses);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ return delegate.getRowCountApproximation();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Table getTable() {
+ return delegate.getTable();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isRowIdIndex() {
+ return delegate.isRowIdIndex();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean needRebuild() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(Session ses) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(Session ses, Row row) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setSortedInsertMode(boolean sortedInsertMode) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void truncate(Session ses) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public Schema getSchema() {
+ return delegate.getSchema();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isHidden() {
+ return delegate.isHidden();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void checkRename() {
+ throw DbException.getUnsupportedException("rename");
+ }
+
+ /** {@inheritDoc} */
+ @Override public ArrayList<DbObject> getChildren() {
+ return delegate.getChildren();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getComment() {
+ return delegate.getComment();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getCreateSQL() {
+ return null; // Scan should return null.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getCreateSQLForCopy(Table tbl, String quotedName) {
+ return delegate.getCreateSQLForCopy(tbl, quotedName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Database getDatabase() {
+ return delegate.getDatabase();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getDropSQL() {
+ return delegate.getDropSQL();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getId() {
+ return delegate.getId();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getName() {
+ return delegate.getName() + SCAN_INDEX_NAME_SUFFIX;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getSQL() {
+ return delegate.getSQL();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getType() {
+ return delegate.getType();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isTemporary() {
+ return delegate.isTemporary();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void removeChildrenAndResources(Session ses) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void rename(String newName) {
+ throw DbException.getUnsupportedException("rename");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setComment(String comment) {
+ throw DbException.getUnsupportedException("comment");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setTemporary(boolean temporary) {
+ throw DbException.getUnsupportedException("temporary");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TreeIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TreeIndex.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TreeIndex.java
new file mode 100644
index 0000000..e0ad5c2
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2TreeIndex.java
@@ -0,0 +1,469 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.ignite.spi.indexing.*;
+import org.gridgain.grid.util.*;
+import org.gridgain.grid.util.snaptree.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+import org.h2.engine.*;
+import org.h2.index.*;
+import org.h2.result.*;
+import org.h2.table.*;
+import org.h2.value.*;
+import org.jetbrains.annotations.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Base class for snapshotable tree indexes.
+ */
+@SuppressWarnings("ComparatorNotSerializable")
+public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridSearchRowPointer> {
+ /** */
+ protected final ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree;
+
+ /** */
+ private final ThreadLocal<ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>> snapshot =
+ new ThreadLocal<>();
+
+ /**
+ * Constructor with index initialization.
+ *
+ * @param name Index name.
+ * @param tbl Table.
+ * @param pk If this index is primary key.
+ * @param keyCol Primary key column index.
+ * @param valCol Value column index.
+ * @param cols Index columns list.
+ */
+ @SuppressWarnings("unchecked")
+ public GridH2TreeIndex(String name, GridH2Table tbl, boolean pk, int keyCol, int valCol, IndexColumn... cols) {
+ super(keyCol, valCol);
+ if (!pk) {
+ // For other indexes we add primary key at the end to avoid conflicts.
+ cols = Arrays.copyOf(cols, cols.length + 1);
+
+ cols[cols.length - 1] = tbl.indexColumn(keyCol, SortOrder.ASCENDING);
+ }
+
+ IndexColumn.mapColumns(cols, tbl);
+
+ initBaseIndex(tbl, 0, name, cols,
+ pk ? IndexType.createUnique(false, false) : IndexType.createNonUnique(false, false, false));
+
+ final GridH2RowDescriptor desc = tbl.rowDescriptor();
+
+ tree = desc == null || desc.memory() == null ? new SnapTreeMap<GridSearchRowPointer, GridH2Row>(this) {
+ @Override protected void afterNodeUpdate_nl(Node<GridSearchRowPointer, GridH2Row> node, Object val) {
+ if (val != null)
+ node.key = (GridSearchRowPointer)val;
+ }
+
+ @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
+ if (key instanceof ComparableRow)
+ return (Comparable<? super SearchRow>)key;
+
+ return super.comparable(key);
+ }
+ } : new GridOffHeapSnapTreeMap<GridSearchRowPointer, GridH2Row>(desc, desc, desc.memory(), desc.guard(), this) {
+ @Override protected void afterNodeUpdate_nl(long node, GridH2Row val) {
+ final long oldKey = keyPtr(node);
+
+ if (val != null) {
+ key(node, val);
+
+ guard.finalizeLater(new Runnable() {
+ @Override public void run() {
+ desc.createPointer(oldKey).decrementRefCount();
+ }
+ });
+ }
+ }
+
+ @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
+ if (key instanceof ComparableRow)
+ return (Comparable<? super SearchRow>)key;
+
+ return super.comparable(key);
+ }
+ };
+ }
+
+ /**
+ * Closes index and releases resources.
+ */
+ public void close() {
+ if (tree instanceof Closeable)
+ U.closeQuiet((Closeable)tree);
+ }
+
+ /**
+ * Takes snapshot to be used in current thread. If argument is null it will be taken from current trees.
+ *
+ * @param s Map to be used as snapshot if not null.
+ * @return Taken snapshot or given argument back.
+ */
+ @SuppressWarnings("unchecked")
+ @Override public Object takeSnapshot(@Nullable Object s) {
+ assert snapshot.get() == null;
+
+ if (s == null)
+ s = tree instanceof SnapTreeMap ? ((SnapTreeMap)tree).clone() :
+ ((GridOffHeapSnapTreeMap)tree).clone();
+
+ snapshot.set((ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>)s);
+
+ return s;
+ }
+
+ /**
+ * Releases snapshot for current thread.
+ */
+ @Override public void releaseSnapshot() {
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> s = snapshot.get();
+
+ snapshot.remove();
+
+ if (s instanceof Closeable)
+ U.closeQuiet((Closeable)s);
+ }
+
+ /**
+ * @return Snapshot for current thread if there is one.
+ */
+ private ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> treeForRead() {
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> res = snapshot.get();
+
+ if (res == null)
+ res = tree;
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close(Session ses) {
+ assert snapshot.get() == null;
+
+ if (tree instanceof Closeable)
+ U.closeQuiet((Closeable)tree);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCount(@Nullable Session ses) {
+ GridIndexingQueryFilter f = filters.get();
+
+ // Fast path if we don't need to perform any filtering.
+ if (f == null || f.forSpace(((GridH2Table)getTable()).spaceName()) == null)
+ return treeForRead().size();
+
+ Iterator<GridH2Row> iter = doFind(null, false, null);
+
+ long size = 0;
+
+ while (iter.hasNext()) {
+ iter.next();
+
+ size++;
+ }
+
+ return size;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ return tree.size();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compare(GridSearchRowPointer r1, GridSearchRowPointer r2) {
+ // Second row here must be data row if first is a search row.
+ return -compareRows(r2, r1);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ SB sb = new SB((indexType.isUnique() ? "Unique index '" : "Index '") + getName() + "' [");
+
+ boolean first = true;
+
+ for (IndexColumn col : getIndexColumns()) {
+ if (first)
+ first = false;
+ else
+ sb.a(", ");
+
+ sb.a(col.getSQL());
+ }
+
+ sb.a(" ]");
+
+ return sb.toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override public double getCost(Session ses, int[] masks, TableFilter filter, SortOrder sortOrder) {
+ return getCostRangeIndex(masks, getRowCountApproximation(), filter, sortOrder);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canFindNext() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor find(Session ses, @Nullable SearchRow first, @Nullable SearchRow last) {
+ return new GridH2Cursor(doFind(first, true, last));
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor findNext(Session ses, SearchRow higherThan, SearchRow last) {
+ return new GridH2Cursor(doFind(higherThan, false, last));
+ }
+
+ /**
+ * Finds row with key equal one in given search row.
+ * WARNING!! Method call must be protected by {@link GridUnsafeGuard#begin()}
+ * {@link GridUnsafeGuard#end()} block.
+ *
+ * @param row Search row.
+ * @return Row.
+ */
+ public GridH2AbstractKeyValueRow findOne(GridSearchRowPointer row) {
+ return (GridH2AbstractKeyValueRow)tree.get(row);
+ }
+
+ /**
+ * Returns sub-tree bounded by given values.
+ *
+ * @param first Lower bound.
+ * @param includeFirst Whether lower bound should be inclusive.
+ * @param last Upper bound always inclusive.
+ * @return Iterator over rows in given range.
+ */
+ @SuppressWarnings("unchecked")
+ private Iterator<GridH2Row> doFind(@Nullable SearchRow first, boolean includeFirst,
+ @Nullable SearchRow last) {
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> t = treeForRead();
+
+ includeFirst &= first != null;
+
+ NavigableMap<GridSearchRowPointer, GridH2Row> range = subTree(t, comparable(first, includeFirst ? -1 : 1),
+ comparable(last, 1));
+
+ if (range == null)
+ return new GridEmptyIterator<>();
+
+ return filter(range.values().iterator());
+ }
+
+ /**
+ * @param row Row.
+ * @param bias Bias.
+ * @return Comparable row.
+ */
+ private GridSearchRowPointer comparable(SearchRow row, int bias) {
+ if (row == null)
+ return null;
+
+ if (bias == 0 && row instanceof GridH2Row)
+ return (GridSearchRowPointer)row;
+
+ return new ComparableRow(row, bias);
+ }
+
+ /**
+ * Takes sup-map from given one.
+ *
+ * @param map Map.
+ * @param first Lower bound.
+ * @param last Upper bound.
+ * @return Sub-map.
+ */
+ @SuppressWarnings({"IfMayBeConditional", "TypeMayBeWeakened"})
+ private NavigableMap<GridSearchRowPointer, GridH2Row> subTree(NavigableMap<GridSearchRowPointer, GridH2Row> map,
+ @Nullable GridSearchRowPointer first, @Nullable GridSearchRowPointer last) {
+ // We take exclusive bounds because it is possible that one search row will be equal to multiple key rows
+ // in tree and we must return them all.
+ if (first == null) {
+ if (last == null)
+ return map;
+ else
+ return map.headMap(last, false);
+ }
+ else {
+ if (last == null)
+ return map.tailMap(first, false);
+ else {
+ if (compare(first, last) > 0)
+ return null;
+
+ return map.subMap(first, false, last, false);
+ }
+ }
+ }
+
+ /**
+ * Gets iterator over all rows in this index.
+ *
+ * @return Rows iterator.
+ */
+ Iterator<GridH2Row> rows() {
+ return doFind(null, false, null);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canGetFirstOrLast() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor findFirstOrLast(Session ses, boolean first) {
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree = treeForRead();
+
+ Iterator<GridH2Row> iter = filter(first ? tree.values().iterator() : tree.descendingMap().values().iterator());
+
+ GridSearchRowPointer res = null;
+
+ if (iter.hasNext())
+ res = iter.next();
+
+ return new SingleRowCursor((Row)res);
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2Row put(GridH2Row row) {
+ return tree.put(row, row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2Row remove(SearchRow row) {
+ return tree.remove(comparable(row, 0));
+ }
+
+ /**
+ * Comparable row with bias. Will be used for queries to have correct bounds (in case of multicolumn index
+ * and query on few first columns we will multiple equal entries in tree).
+ */
+ private class ComparableRow implements GridSearchRowPointer, Comparable<SearchRow> {
+ /** */
+ private final SearchRow row;
+
+ /** */
+ private final int bias;
+
+ /**
+ * @param row Row.
+ * @param bias Bias.
+ */
+ private ComparableRow(SearchRow row, int bias) {
+ this.row = row;
+ this.bias = bias;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compareTo(SearchRow o) {
+ int res = compareRows(o, row);
+
+ if (res == 0)
+ return bias;
+
+ return -res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object obj) {
+ throw new IllegalStateException("Should never be called.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getColumnCount() {
+ return row.getColumnCount();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Value getValue(int idx) {
+ return row.getValue(idx);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setValue(int idx, Value v) {
+ row.setValue(idx, v);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setKeyAndVersion(SearchRow old) {
+ row.setKeyAndVersion(old);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getVersion() {
+ return row.getVersion();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setKey(long key) {
+ row.setKey(key);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getKey() {
+ return row.getKey();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getMemory() {
+ return row.getMemory();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long pointer() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void incrementRefCount() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void decrementRefCount() {
+ throw new IllegalStateException();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2TreeIndex rebuild() throws InterruptedException {
+ IndexColumn[] cols = getIndexColumns();
+
+ if (!getIndexType().isUnique())
+ cols = Arrays.copyOf(cols, cols.length - 1);
+
+ GridH2TreeIndex idx = new GridH2TreeIndex(getName(), (GridH2Table)getTable(), getIndexType().isUnique(),
+ keyCol, valCol, cols);
+
+ Thread thread = Thread.currentThread();
+
+ long i = 0;
+
+ for (GridH2Row row : tree.values()) {
+ // Check for interruptions every 1000 iterations.
+ if (++i % 1000 == 0 && thread.isInterrupted())
+ throw new InterruptedException();
+
+ idx.tree.put(row, row);
+ }
+
+ return idx;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Utils.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Utils.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Utils.java
new file mode 100644
index 0000000..661945f
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridH2Utils.java
@@ -0,0 +1,125 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.h2.value.*;
+
+import java.sql.*;
+import java.util.*;
+
+/**
+ *
+ */
+@SuppressWarnings({"JavaAbbreviationUsage", "GridBracket"})
+public class GridH2Utils {
+ /** Copy/pasted from org.h2.util.DateTimeUtils */
+ private static final int SHIFT_YEAR = 9;
+
+ /** Copy/pasted from org.h2.util.DateTimeUtils */
+ private static final int SHIFT_MONTH = 5;
+
+ /** Static calendar. */
+ private static final Calendar staticCalendar = Calendar.getInstance();
+
+ /** */
+ private static final ThreadLocal<Calendar> localCalendar = new ThreadLocal<>();
+
+ /**
+ * @return The instance of calendar for local thread.
+ */
+ public static Calendar getLocalCalendar() {
+ Calendar res = localCalendar.get();
+
+ if (res == null) {
+ res = (Calendar)staticCalendar.clone();
+
+ localCalendar.set(res);
+ }
+
+ return res;
+ }
+
+ /**
+ * Get or create a timestamp value for the given timestamp.
+ *
+ * Copy/pasted from org.h2.value.ValueTimestamp#get(java.sql.Timestamp)
+ *
+ * @param timestamp The timestamp.
+ * @return The value.
+ */
+ public static ValueTimestamp toValueTimestamp(Timestamp timestamp) {
+ long ms = timestamp.getTime();
+ long nanos = timestamp.getNanos() % 1000000;
+
+ Calendar calendar = getLocalCalendar();
+
+ calendar.clear();
+ calendar.setTimeInMillis(ms);
+
+ long dateValue = dateValueFromCalendar(calendar);
+
+ nanos += nanosFromCalendar(calendar);
+
+ return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
+ }
+
+ /**
+ * Calculate the nanoseconds since midnight from a given calendar.
+ *
+ * Copy/pasted from org.h2.util.DateTimeUtils#nanosFromCalendar(java.util.Calendar).
+ *
+ * @param cal The calendar.
+ * @return Nanoseconds.
+ */
+ private static long nanosFromCalendar(Calendar cal) {
+ int h = cal.get(Calendar.HOUR_OF_DAY);
+ int m = cal.get(Calendar.MINUTE);
+ int s = cal.get(Calendar.SECOND);
+ int millis = cal.get(Calendar.MILLISECOND);
+
+ return ((((((h * 60L) + m) * 60) + s) * 1000) + millis) * 1000000;
+ }
+
+ /**
+ * Calculate the date value from a given calendar.
+ *
+ * Copy/pasted from org.h2.util.DateTimeUtils#dateValueFromCalendar(java.util.Calendar)
+ *
+ * @param cal The calendar.
+ * @return The date value.
+ */
+ private static long dateValueFromCalendar(Calendar cal) {
+ int year, month, day;
+
+ year = getYear(cal);
+ month = cal.get(Calendar.MONTH) + 1;
+ day = cal.get(Calendar.DAY_OF_MONTH);
+
+ return ((long) year << SHIFT_YEAR) | (month << SHIFT_MONTH) | day;
+ }
+
+ /**
+ * Get the year (positive or negative) from a calendar.
+ *
+ * Copy/pasted from org.h2.util.DateTimeUtils#getYear(java.util.Calendar)
+ *
+ * @param calendar The calendar.
+ * @return The year.
+ */
+ private static int getYear(Calendar calendar) {
+ int year = calendar.get(Calendar.YEAR);
+
+ if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
+ year = 1 - year;
+ }
+
+ return year;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneDirectory.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneDirectory.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneDirectory.java
new file mode 100644
index 0000000..6bd0f46
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneDirectory.java
@@ -0,0 +1,189 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import org.apache.lucene.store.*;
+import org.gridgain.grid.util.offheap.unsafe.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A memory-resident {@link Directory} implementation.
+ */
+public class GridLuceneDirectory extends Directory {
+ /** */
+ protected final Map<String, GridLuceneFile> fileMap = new ConcurrentHashMap<>();
+
+ /** */
+ protected final AtomicLong sizeInBytes = new AtomicLong();
+
+ /** */
+ private final GridUnsafeMemory mem;
+
+ /**
+ * Constructs an empty {@link Directory}.
+ *
+ * @param mem Memory.
+ */
+ public GridLuceneDirectory(GridUnsafeMemory mem) {
+ this.mem = mem;
+
+ try {
+ setLockFactory(new GridLuceneLockFactory());
+ }
+ catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public final String[] listAll() {
+ ensureOpen();
+ // NOTE: fileMap.keySet().toArray(new String[0]) is broken in non Sun JDKs,
+ // and the code below is resilient to map changes during the array population.
+ Set<String> fileNames = fileMap.keySet();
+
+ List<String> names = new ArrayList<>(fileNames.size());
+
+ for (String name : fileNames)
+ names.add(name);
+
+ return names.toArray(new String[names.size()]);
+ }
+
+ /** {@inheritDoc} */
+ @Override public final boolean fileExists(String name) {
+ ensureOpen();
+
+ return fileMap.containsKey(name);
+ }
+
+ /** {@inheritDoc} */
+ @Override public final long fileModified(String name) {
+ ensureOpen();
+
+ throw new IllegalStateException(name);
+ }
+
+ /**
+ * Set the modified time of an existing file to now.
+ *
+ * @throws IOException if the file does not exist
+ */
+ @Override public void touchFile(String name) throws IOException {
+ ensureOpen();
+
+ throw new IllegalStateException(name);
+ }
+
+ /** {@inheritDoc} */
+ @Override public final long fileLength(String name) throws IOException {
+ ensureOpen();
+
+ GridLuceneFile file = fileMap.get(name);
+
+ if (file == null)
+ throw new FileNotFoundException(name);
+
+ return file.getLength();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void deleteFile(String name) throws IOException {
+ ensureOpen();
+
+ doDeleteFile(name);
+ }
+
+ /**
+ * Deletes file.
+ *
+ * @param name File name.
+ * @throws IOException If failed.
+ */
+ private void doDeleteFile(String name) throws IOException {
+ GridLuceneFile file = fileMap.remove(name);
+
+ if (file != null) {
+ file.delete();
+
+ sizeInBytes.addAndGet(-file.getSizeInBytes());
+ }
+ else
+ throw new FileNotFoundException(name);
+ }
+
+ /** {@inheritDoc} */
+ @Override public IndexOutput createOutput(String name) throws IOException {
+ ensureOpen();
+
+ GridLuceneFile file = newRAMFile();
+
+ GridLuceneFile existing = fileMap.remove(name);
+
+ if (existing != null) {
+ sizeInBytes.addAndGet(-existing.getSizeInBytes());
+
+ existing.delete();
+ }
+
+ fileMap.put(name, file);
+
+ return new GridLuceneOutputStream(file);
+ }
+
+ /**
+ * Returns a new {@link GridLuceneFile} for storing data. This method can be
+ * overridden to return different {@link GridLuceneFile} impls, that e.g. override.
+ *
+ * @return New ram file.
+ */
+ protected GridLuceneFile newRAMFile() {
+ return new GridLuceneFile(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public IndexInput openInput(String name) throws IOException {
+ ensureOpen();
+
+ GridLuceneFile file = fileMap.get(name);
+
+ if (file == null)
+ throw new FileNotFoundException(name);
+
+ return new GridLuceneInputStream(name, file);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close() {
+ isOpen = false;
+
+ for (String fileName : fileMap.keySet()) {
+ try {
+ doDeleteFile(fileName);
+ }
+ catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ assert fileMap.isEmpty();
+ }
+
+ /**
+ * @return Memory.
+ */
+ GridUnsafeMemory memory() {
+ return mem;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneFile.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneFile.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneFile.java
new file mode 100644
index 0000000..6461822
--- /dev/null
+++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/opt/GridLuceneFile.java
@@ -0,0 +1,186 @@
+/* @java.file.header */
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.query.h2.opt;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import static org.gridgain.grid.kernal.processors.query.h2.opt.GridLuceneOutputStream.*;
+
+/**
+ * Lucene file.
+ */
+public class GridLuceneFile implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ public static final AtomicInteger filesCnt = new AtomicInteger();
+
+ /** */
+ private LongArray buffers = new LongArray();
+
+ /** */
+ private long length;
+
+ /** */
+ private final GridLuceneDirectory dir;
+
+ /** */
+ private volatile long sizeInBytes;
+
+ /**
+ * File used as buffer, in no RAMDirectory
+ *
+ * @param dir Directory.
+ */
+ GridLuceneFile(GridLuceneDirectory dir) {
+ this.dir = dir;
+
+ filesCnt.incrementAndGet();
+ }
+
+ /**
+ * For non-stream access from thread that might be concurrent with writing
+ *
+ * @return Length.
+ */
+ public synchronized long getLength() {
+ return length;
+ }
+
+ /**
+ * Sets length.
+ *
+ * @param length Length.
+ */
+ protected synchronized void setLength(long length) {
+ this.length = length;
+ }
+
+ /**
+ * @return New buffer address.
+ */
+ final long addBuffer() {
+ long buf = newBuffer();
+
+ synchronized (this) {
+ buffers.add(buf);
+
+ sizeInBytes += BUFFER_SIZE;
+ }
+
+ if (dir != null)
+ dir.sizeInBytes.getAndAdd(BUFFER_SIZE);
+
+ return buf;
+ }
+
+ /**
+ * Gets address of buffer.
+ *
+ * @param idx Index.
+ * @return Pointer.
+ */
+ protected final synchronized long getBuffer(int idx) {
+ return buffers.get(idx);
+ }
+
+ /**
+ * @return Number of buffers.
+ */
+ protected final synchronized int numBuffers() {
+ return buffers.size();
+ }
+
+ /**
+ * Expert: allocate a new buffer.
+ * Subclasses can allocate differently.
+ *
+ * @return allocated buffer.
+ */
+ protected long newBuffer() {
+ return dir.memory().allocate(BUFFER_SIZE);
+ }
+
+ /**
+ * Deletes file and deallocates memory..
+ */
+ public synchronized void delete() {
+ if (buffers == null)
+ return;
+
+ for (int i = 0; i < buffers.idx; i++)
+ dir.memory().release(buffers.arr[i], BUFFER_SIZE);
+
+ buffers = null;
+
+ filesCnt.decrementAndGet();
+ }
+
+ /**
+ * @return Size in bytes.
+ */
+ public long getSizeInBytes() {
+ return sizeInBytes;
+ }
+
+ /**
+ * @return Directory.
+ */
+ public GridLuceneDirectory getDirectory() {
+ return dir;
+ }
+
+ /**
+ * Simple expandable long[] wrapper.
+ */
+ private static class LongArray {
+ /** */
+ private long[] arr = new long[128];
+
+ /** */
+ private int idx;
+
+ /**
+ * @return Size.
+ */
+ int size() {
+ return idx;
+ }
+
+ /**
+ * Gets value by index.
+ *
+ * @param idx Index.
+ * @return Value.
+ */
+ long get(int idx) {
+ assert idx < this.idx;
+
+ return arr[idx];
+ }
+
+ /**
+ * Adds value.
+ *
+ * @param val Value.
+ */
+ void add(long val) {
+ int len = arr.length;
+
+ if (idx == len)
+ arr = Arrays.copyOf(arr, Math.min(len * 2, len + 1024));
+
+ arr[idx++] = val;
+ }
+ }
+}
[17/17] incubator-ignite git commit: Merge branches 'ignite-qry' and
'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite
Posted by se...@apache.org.
Merge branches 'ignite-qry' and 'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/7b13de91
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/7b13de91
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/7b13de91
Branch: refs/heads/master
Commit: 7b13de91745a1c3f95715a4724a325421c16d8e7
Parents: 73b5ef6 7f6fdca
Author: S.Vladykin <sv...@gridgain.com>
Authored: Wed Dec 10 18:58:03 2014 +0300
Committer: S.Vladykin <sv...@gridgain.com>
Committed: Wed Dec 10 18:58:03 2014 +0300
----------------------------------------------------------------------
.../src/main/java/org/apache/ignite/Ignite.java | 22 +-
.../java/org/apache/ignite/IgniteCache.java | 300 +++++++++++++++++++
.../apache/ignite/cache/CacheConfiguration.java | 23 ++
.../apache/ignite/cache/CacheEntryEvent.java | 36 +++
.../java/org/apache/ignite/cache/CacheFlag.java | 68 +++++
.../org/apache/ignite/cache/CachePeekMode.java | 72 +++++
.../ignite/cache/eviction/EvictableEntry.java | 39 +++
.../cache/query/QueryAffinityPredicate.java | 124 ++++++++
.../cache/query/QueryContinuousPredicate.java | 204 +++++++++++++
.../apache/ignite/cache/query/QueryCursor.java | 29 ++
.../ignite/cache/query/QueryPredicate.java | 68 +++++
.../apache/ignite/cache/query/QueryReducer.java | 22 ++
.../ignite/cache/query/QuerySqlPredicate.java | 107 +++++++
.../ignite/cache/query/QueryTextPredicate.java | 79 +++++
.../query/annotations/QueryGroupIndex.java | 50 ++++
.../cache/query/annotations/QuerySqlField.java | 125 ++++++++
.../query/annotations/QuerySqlFunction.java | 59 ++++
.../cache/query/annotations/QueryTextField.java | 25 ++
.../ignite/spi/deployment/DeploymentSpi.java | 2 +-
.../org/gridgain/grid/kernal/GridKernal.java | 5 +
modules/core/src/test/config/tests.properties | 2 +-
.../java/org/gridgain/grid/GridSpringBean.java | 5 +
...loymentClassLoaderMultiThreadedSelfTest.java | 4 +-
.../GridUriDeploymentFileProcessorSelfTest.java | 2 +-
.../GridUriDeploymentMultiScannersSelfTest.java | 2 +-
.../file/GridFileDeploymentSelfTest.java | 24 +-
.../GridFileDeploymentUndeploySelfTest.java | 4 +-
.../uri/scanners/ftp/GridFtpDeploymentTest.java | 2 +-
.../http/GridHttpDeploymentSelfTest.java | 2 +-
pom.xml | 34 ++-
30 files changed, 1496 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/7b13de91/modules/core/src/main/java/org/gridgain/grid/kernal/GridKernal.java
----------------------------------------------------------------------
[14/17] incubator-ignite git commit: Merge branches 'ignite-qry' and
'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into
ignite-qry
Posted by se...@apache.org.
Merge branches 'ignite-qry' and 'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-qry
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/2a605d1a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/2a605d1a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/2a605d1a
Branch: refs/heads/master
Commit: 2a605d1ad3cde56b7963c1e50809c6f47ac1e355
Parents: 59204a5 20872dc
Author: S.Vladykin <sv...@gridgain.com>
Authored: Wed Dec 10 12:07:57 2014 +0300
Committer: S.Vladykin <sv...@gridgain.com>
Committed: Wed Dec 10 12:07:57 2014 +0300
----------------------------------------------------------------------
config/hadoop/default-config.xml | 6 +-
.../fs/IgniteFsGroupDataBlocksKeyMapper.java | 2 +-
.../ignite/fs/mapreduce/IgniteFsTask.java | 2 +-
.../processors/cache/GridCacheMapEntry.java | 40 ++++--
.../processors/cache/GridCacheSwapManager.java | 14 +-
.../distributed/dht/GridDhtLocalPartition.java | 32 +++++
.../distributed/dht/GridDhtLockFuture.java | 3 +
.../distributed/dht/GridDhtLockResponse.java | 12 ++
.../dht/GridDhtTransactionalCacheAdapter.java | 2 +
.../colocated/GridDhtDetachedCacheEntry.java | 5 +
.../dht/preloader/GridDhtPreloader.java | 10 +-
.../cache/GridCacheOffheapUpdateSelfTest.java | 130 +++++++++++++++++++
...IpcEndpointRegistrationAbstractSelfTest.java | 4 +-
.../bamboo/GridDataGridTestSuite.java | 1 +
14 files changed, 235 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
[04/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2ResultSetIterator.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2ResultSetIterator.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2ResultSetIterator.java
deleted file mode 100644
index c37752f..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2ResultSetIterator.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.apache.ignite.spi.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.typedef.internal.*;
-
-import java.sql.*;
-import java.util.*;
-
-
-/**
- * Iterator over result set.
- */
-abstract class GridH2ResultSetIterator<T> implements IgniteSpiCloseableIterator<T> {
- /** */
- private static final long serialVersionUID = 0L;
-
- /** */
- private final ResultSet data;
-
- /** */
- protected final Object[] row;
-
- /** */
- private boolean hasRow;
-
- /**
- * @param data Data array.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- protected GridH2ResultSetIterator(ResultSet data) throws IgniteSpiException {
- this.data = data;
-
- if (data != null) {
- try {
- row = new Object[data.getMetaData().getColumnCount()];
- }
- catch (SQLException e) {
- throw new IgniteSpiException(e);
- }
- }
- else
- row = null;
- }
-
- /**
- * @return {@code true} If next row was fetched successfully.
- */
- private boolean fetchNext() {
- if (data == null)
- return false;
-
- try {
- if (!data.next())
- return false;
-
- for (int c = 0; c < row.length; c++)
- row[c] = data.getObject(c + 1);
-
- return true;
- }
- catch (SQLException e) {
- throw new GridRuntimeException(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override public boolean hasNext() {
- return hasRow || (hasRow = fetchNext());
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("IteratorNextCanNotThrowNoSuchElementException")
- @Override public T next() {
- if (!hasNext())
- throw new NoSuchElementException();
-
- hasRow = false;
-
- return createRow();
- }
-
- /**
- * @return Row.
- */
- protected abstract T createRow();
-
- /** {@inheritDoc} */
- @Override public void remove() {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override public void close() throws GridException {
- if (data == null)
- // Nothing to close.
- return;
-
- try {
- U.closeQuiet(data.getStatement());
- }
- catch (SQLException e) {
- throw new GridException(e);
- }
-
- U.closeQuiet(data);
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString((Class<GridH2ResultSetIterator>)getClass(), this);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2AbstractKeyValueRow.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2AbstractKeyValueRow.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2AbstractKeyValueRow.java
deleted file mode 100644
index ce56b57..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2AbstractKeyValueRow.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.ignite.spi.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.h2.message.*;
-import org.h2.result.*;
-import org.h2.value.*;
-import org.jetbrains.annotations.*;
-
-import java.lang.ref.*;
-import java.math.*;
-import java.sql.Date;
-import java.sql.*;
-import java.util.*;
-
-/**
- * Table row implementation based on {@link org.apache.ignite.spi.indexing.IndexingTypeDescriptor}.
- */
-public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
- /** */
- private static final int DEFAULT_COLUMNS_COUNT = 2;
-
- /** Key column. */
- public static final int KEY_COL = 0;
-
- /** Value column. */
- public static final int VAL_COL = 1;
-
- /** */
- protected final GridH2RowDescriptor desc;
-
- /** */
- @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
- protected long expirationTime;
-
- /**
- * Constructor.
- *
- * @param desc Row descriptor.
- * @param key Key.
- * @param keyType Key type.
- * @param val Value.
- * @param valType Value type.
- * @param expirationTime Expiration time.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- protected GridH2AbstractKeyValueRow(GridH2RowDescriptor desc, Object key, int keyType, @Nullable Object val,
- int valType, long expirationTime) throws IgniteSpiException {
- super(wrap(key, keyType),
- val == null ? null : wrap(val, valType)); // We remove by key only, so value can be null here.
-
- this.desc = desc;
- this.expirationTime = expirationTime;
- }
-
- /**
- * Protected constructor for {@link GridH2KeyValueRowOffheap}
- *
- * @param desc Row descriptor.
- */
- protected GridH2AbstractKeyValueRow(GridH2RowDescriptor desc) {
- super(new Value[DEFAULT_COLUMNS_COUNT]);
-
- this.desc = desc;
- }
-
- /**
- * Wraps object to respective {@link Value}.
- *
- * @param obj Object.
- * @param type Value type.
- * @return Value.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private static Value wrap(Object obj, int type) throws IgniteSpiException {
- switch (type) {
- case Value.BOOLEAN:
- return ValueBoolean.get((Boolean)obj);
- case Value.BYTE:
- return ValueByte.get((Byte)obj);
- case Value.SHORT:
- return ValueShort.get((Short)obj);
- case Value.INT:
- return ValueInt.get((Integer)obj);
- case Value.FLOAT:
- return ValueFloat.get((Float)obj);
- case Value.LONG:
- return ValueLong.get((Long)obj);
- case Value.DOUBLE:
- return ValueDouble.get((Double)obj);
- case Value.UUID:
- UUID uuid = (UUID)obj;
- return ValueUuid.get(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
- case Value.DATE:
- return ValueDate.get((Date)obj);
- case Value.TIME:
- return ValueTime.get((Time)obj);
- case Value.TIMESTAMP:
- if (obj instanceof java.util.Date && !(obj instanceof Timestamp))
- obj = new Timestamp(((java.util.Date) obj).getTime());
-
- return GridH2Utils.toValueTimestamp((Timestamp)obj);
- case Value.DECIMAL:
- return ValueDecimal.get((BigDecimal)obj);
- case Value.STRING:
- return ValueString.get(obj.toString());
- case Value.BYTES:
- return ValueBytes.get((byte[])obj);
- case Value.JAVA_OBJECT:
- return ValueJavaObject.getNoCopy(obj, null, null);
- case Value.ARRAY:
- Object[] arr = (Object[])obj;
-
- Value[] valArr = new Value[arr.length];
-
- for (int i = 0; i < arr.length; i++) {
- Object o = arr[i];
-
- valArr[i] = o == null ? ValueNull.INSTANCE : wrap(o, DataType.getTypeFromClass(o.getClass()));
- }
-
- return ValueArray.get(valArr);
-
- case Value.GEOMETRY:
- return ValueGeometry.getFromGeometry(obj);
- }
-
- throw new IgniteSpiException("Failed to wrap value[type=" + type + ", value=" + obj + "]");
- }
-
- /**
- * @return Expiration time of respective cache entry.
- */
- public long expirationTime() {
- return expirationTime;
- }
-
- /** {@inheritDoc} */
- @Override public int getColumnCount() {
- return DEFAULT_COLUMNS_COUNT + desc.fieldsCount();
- }
-
- /**
- * Should be called to remove reference on value.
- *
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public synchronized void onSwap() throws GridException {
- setValue(VAL_COL, null);
- }
-
- /**
- * Should be called when entry getting unswapped.
- *
- * @param val Value.
- * @throws GridException If failed.
- */
- public synchronized void onUnswap(Object val) throws GridException {
- setValue(VAL_COL, wrap(val, desc.valueType()));
- }
-
- /**
- * Atomically updates weak value.
- *
- * @param exp Expected value.
- * @param upd New value.
- * @return Expected value if update succeeded, unexpected value otherwise.
- */
- protected synchronized Value updateWeakValue(Value exp, Value upd) {
- Value res = super.getValue(VAL_COL);
-
- if (res != exp && !(res instanceof WeakValue))
- return res;
-
- setValue(VAL_COL, new WeakValue(upd));
-
- return exp;
- }
-
- /**
- * @return Synchronized value.
- */
- protected synchronized Value syncValue() {
- return super.getValue(VAL_COL);
- }
-
- /** {@inheritDoc} */
- @Override public Value getValue(int col) {
- if (col < DEFAULT_COLUMNS_COUNT) {
- Value v = super.getValue(col);
-
- if (col == VAL_COL) {
- while ((v = WeakValue.unwrap(v)) == null) {
- v = getOffheapValue(VAL_COL);
-
- if (v != null) {
- setValue(VAL_COL, v);
-
- if (super.getValue(KEY_COL) == null)
- cache();
-
- return v;
- }
-
- try {
- Object valObj = desc.readFromSwap(getValue(KEY_COL).getObject());
-
- if (valObj != null) {
- Value upd = wrap(valObj, desc.valueType());
-
- Value res = updateWeakValue(v, upd);
-
- if (res == v) {
- if (super.getValue(KEY_COL) == null)
- cache();
-
- return upd;
- }
-
- v = res;
- }
- else {
- // If nothing found in swap then we should be already unswapped.
- v = syncValue();
- }
- }
- catch (GridException e) {
- throw new GridRuntimeException(e);
- }
- }
- }
-
- if (v == null) {
- assert col == KEY_COL : col;
-
- v = getOffheapValue(KEY_COL);
-
- assert v != null : v;
-
- setValue(KEY_COL, v);
-
- if (super.getValue(VAL_COL) == null)
- cache();
- }
-
- assert !(v instanceof WeakValue) : v;
-
- return v;
- }
-
- col -= DEFAULT_COLUMNS_COUNT;
-
- assert col >= 0;
-
- Value v = getValue(desc.isKeyColumn(col) ? KEY_COL : VAL_COL);
-
- if (v == null)
- return null;
-
- Object obj = v.getObject();
-
- Object res = desc.columnValue(obj, col);
-
- if (res == null)
- return ValueNull.INSTANCE;
-
- try {
- return wrap(res, desc.fieldType(col));
- }
- catch (IgniteSpiException e) {
- throw DbException.convert(e);
- }
- }
-
- /**
- * Caches this row for reuse.
- */
- protected abstract void cache();
-
- /**
- * @param col Column.
- * @return Value read from offheap memory or null if it is impossible.
- */
- protected abstract Value getOffheapValue(int col);
-
- /** {@inheritDoc} */
- @Override public String toString() {
- SB sb = new SB("Row@");
-
- sb.a(Integer.toHexString(System.identityHashCode(this)));
-
- Value v = super.getValue(KEY_COL);
- sb.a("[ key: ").a(v == null ? "nil" : v.getString());
-
- v = WeakValue.unwrap(super.getValue(VAL_COL));
- sb.a(", val: ").a(v == null ? "nil" : v.getString());
-
- sb.a(" ][ ");
-
- if (v != null) {
- for (int i = 2, cnt = getColumnCount(); i < cnt; i++) {
- v = getValue(i);
-
- if (i != 2)
- sb.a(", ");
-
- sb.a(v == null ? "nil" : v.getString());
- }
- }
-
- sb.a(" ]");
-
- return sb.toString();
- }
-
- /** {@inheritDoc} */
- @Override public void setKeyAndVersion(SearchRow old) {
- assert false;
- }
-
- /** {@inheritDoc} */
- @Override public void setKey(long key) {
- assert false;
- }
-
- /** {@inheritDoc} */
- @Override public Row getCopy() {
- assert false;
-
- return null;
- }
-
- /** {@inheritDoc} */
- @Override public void setDeleted(boolean deleted) {
- assert false;
- }
-
- /** {@inheritDoc} */
- @Override public long getKey() {
- assert false;
-
- return 0;
- }
-
- /** {@inheritDoc} */
- @Override public void setSessionId(int sesId) {
- assert false;
- }
-
- /** {@inheritDoc} */
- @Override public void setVersion(int ver) {
- assert false;
- }
-
- /**
- * Weak reference to value that was swapped but accessed in indexing SPI.
- */
- private static class WeakValue extends Value {
- /**
- * Unwraps value.
- *
- * @param v Value.
- * @return Unwrapped value.
- */
- static Value unwrap(Value v) {
- return (v instanceof WeakValue) ? ((WeakValue)v).get() : v;
- }
-
- /** */
- private final WeakReference<Value> ref;
-
- /**
- * @param v Value.
- */
- private WeakValue(Value v) {
- ref = new WeakReference<>(v);
- }
-
- /**
- * @return Referenced value.
- */
- public Value get() {
- return ref.get();
- }
-
- /** {@inheritDoc} */
- @Override public String getSQL() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public int getType() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public long getPrecision() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public int getDisplaySize() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public String getString() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public Object getObject() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public void set(PreparedStatement preparedStatement, int i) throws SQLException {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override protected int compareSecure(Value val, CompareMode compareMode) {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public int hashCode() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(Object o) {
- throw new IllegalStateException();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Cursor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Cursor.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Cursor.java
deleted file mode 100644
index 46c3581..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Cursor.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.h2.index.*;
-import org.h2.message.*;
-import org.h2.result.*;
-
-import java.util.*;
-
-/**
- * H2 Cursor implementation.
- */
-public class GridH2Cursor implements Cursor {
- /** */
- private Iterator<GridH2Row> iter;
-
- /** */
- private Row row;
-
- /**
- * Constructor.
- *
- * @param iter Rows iterator.
- */
- public GridH2Cursor(Iterator<GridH2Row> iter) {
- this.iter = iter;
- }
-
- /** {@inheritDoc} */
- @Override public Row get() {
- return row;
- }
-
- /** {@inheritDoc} */
- @Override public SearchRow getSearchRow() {
- return get();
- }
-
- /** {@inheritDoc} */
- @Override public boolean next() {
- row = null;
-
- if (iter.hasNext())
- row = iter.next();
-
- return row != null;
- }
-
- /** {@inheritDoc} */
- @Override public boolean previous() {
- // Should never be called.
- throw DbException.getUnsupportedException("previous");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2IndexBase.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2IndexBase.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2IndexBase.java
deleted file mode 100644
index af07538..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2IndexBase.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.lang.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.h2.engine.*;
-import org.h2.index.*;
-import org.h2.message.*;
-import org.h2.result.*;
-import org.jetbrains.annotations.*;
-
-import java.util.*;
-
-/**
- * Index base.
- */
-public abstract class GridH2IndexBase extends BaseIndex {
- /** */
- protected static final ThreadLocal<IndexingQueryFilter> filters = new ThreadLocal<>();
-
- /** */
- protected final int keyCol;
-
- /** */
- protected final int valCol;
-
- /**
- * @param keyCol Key column.
- * @param valCol Value column.
- */
- protected GridH2IndexBase(int keyCol, int valCol) {
- this.keyCol = keyCol;
- this.valCol = valCol;
- }
-
- /**
- * Sets key filters for current thread.
- *
- * @param fs Filters.
- */
- public static void setFiltersForThread(IndexingQueryFilter fs) {
- filters.set(fs);
- }
-
- /**
- * If the index supports rebuilding it has to creates its own copy.
- *
- * @return Rebuilt copy.
- * @throws InterruptedException If interrupted.
- */
- public GridH2IndexBase rebuild() throws InterruptedException {
- return this;
- }
-
- /**
- * Put row if absent.
- *
- * @param row Row.
- * @return Existing row or {@code null}.
- */
- public abstract GridH2Row put(GridH2Row row);
-
- /**
- * Remove row from index.
- *
- * @param row Row.
- * @return Removed row.
- */
- public abstract GridH2Row remove(SearchRow row);
-
- /**
- * Takes or sets existing snapshot to be used in current thread.
- *
- * @param s Optional existing snapshot to use.
- * @return Snapshot.
- */
- public Object takeSnapshot(@Nullable Object s) {
- return s;
- }
-
- /**
- * Releases snapshot for current thread.
- */
- public void releaseSnapshot() {
- // No-op.
- }
-
- /**
- * Filters rows from expired ones and using predicate.
- *
- * @param iter Iterator over rows.
- * @return Filtered iterator.
- */
- protected Iterator<GridH2Row> filter(Iterator<GridH2Row> iter) {
- IgniteBiPredicate<Object, Object> p = null;
-
- IndexingQueryFilter f = filters.get();
-
- if (f != null) {
- String spaceName = ((GridH2Table)getTable()).spaceName();
-
- try {
- p = f.forSpace(spaceName);
- }
- catch (GridException e) {
- throw new GridRuntimeException(e);
- }
- }
-
- return new FilteringIterator(iter, U.currentTimeMillis(), p);
- }
-
- /** {@inheritDoc} */
- @Override public long getDiskSpaceUsed() {
- return 0;
- }
-
- /** {@inheritDoc} */
- @Override public void checkRename() {
- throw DbException.getUnsupportedException("rename");
- }
-
- /** {@inheritDoc} */
- @Override public void add(Session ses, Row row) {
- throw DbException.getUnsupportedException("add");
- }
-
- /** {@inheritDoc} */
- @Override public void remove(Session ses, Row row) {
- throw DbException.getUnsupportedException("remove row");
- }
-
- /** {@inheritDoc} */
- @Override public void remove(Session ses) {
- throw DbException.getUnsupportedException("remove index");
- }
-
- /** {@inheritDoc} */
- @Override public void truncate(Session ses) {
- throw DbException.getUnsupportedException("truncate");
- }
-
- /** {@inheritDoc} */
- @Override public boolean needRebuild() {
- return false;
- }
-
- /**
- * Iterator which filters by expiration time and predicate.
- */
- protected class FilteringIterator extends GridFilteredIterator<GridH2Row> {
- /** */
- private final IgniteBiPredicate<Object, Object> fltr;
-
- /** */
- private final long time;
-
- /**
- * @param iter Iterator.
- * @param time Time for expired rows filtering.
- */
- protected FilteringIterator(Iterator<GridH2Row> iter, long time,
- IgniteBiPredicate<Object, Object> fltr) {
- super(iter);
-
- this.time = time;
- this.fltr = fltr;
- }
-
- /**
- * @param row Row.
- * @return If this row was accepted.
- */
- @SuppressWarnings("unchecked")
- @Override protected boolean accept(GridH2Row row) {
- if (row instanceof GridH2AbstractKeyValueRow) {
- if (((GridH2AbstractKeyValueRow) row).expirationTime() <= time)
- return false;
- }
-
- if (fltr == null)
- return true;
-
- Object key = row.getValue(keyCol).getObject();
- Object val = row.getValue(valCol).getObject();
-
- assert key != null;
- assert val != null;
-
- return fltr.apply(key, val);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOffheap.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOffheap.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOffheap.java
deleted file mode 100644
index ec6127b..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOffheap.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.ignite.spi.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-import org.h2.store.*;
-import org.h2.value.*;
-import org.jetbrains.annotations.*;
-
-import java.util.concurrent.locks.*;
-
-/**
- * Offheap row.
- */
-public class GridH2KeyValueRowOffheap extends GridH2AbstractKeyValueRow {
- /** */
- private static final GridStripedLock lock;
-
- /**
- * Init locks.
- */
- static {
- int cpus = Runtime.getRuntime().availableProcessors();
-
- lock = new GridStripedLock(cpus * cpus * 8);
- }
-
- /** */
- private static final int OFFSET_KEY_SIZE = 4; // 4 after ref cnt int
-
- /** */
- private static final int OFFSET_VALUE_REF = OFFSET_KEY_SIZE + 4; // 8
-
- /** */
- private static final int OFFSET_EXPIRATION = OFFSET_VALUE_REF + 8; // 16
-
- /** */
- private static final int OFFSET_KEY = OFFSET_EXPIRATION + 8; // 24
-
- /** */
- private static final int OFFSET_VALUE = 4; // 4 on separate page after val size int
-
- /** */
- private static final Data SIZE_CALCULATOR = Data.create(null, null);
-
- /** */
- @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
- private long ptr;
-
- /**
- * @param desc Row descriptor.
- * @param ptr Pointer.
- */
- public GridH2KeyValueRowOffheap(GridH2RowDescriptor desc, long ptr) {
- super(desc);
-
- assert ptr > 0 : ptr;
-
- this.ptr = ptr;
- }
-
- /**
- * Constructor.
- *
- * @param desc Row descriptor.
- * @param key Key.
- * @param keyType Key type.
- * @param val Value.
- * @param valType Value type.
- * @param expirationTime Expiration time.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public GridH2KeyValueRowOffheap(GridH2RowDescriptor desc, Object key, int keyType, @Nullable Object val, int valType,
- long expirationTime) throws IgniteSpiException {
- super(desc, key, keyType, val, valType, expirationTime);
- }
-
- /** {@inheritDoc} */
- @Override public long expirationTime() {
- if (expirationTime == 0) {
- long p = ptr;
-
- assert p > 0 : p;
-
- // We don't need any synchronization or volatility here because we publish via
- // volatile write to tree node.
- expirationTime = desc.memory().readLong(p + OFFSET_EXPIRATION);
- }
-
- return expirationTime;
- }
-
- /** {@inheritDoc} */
- @Override protected void cache() {
- desc.cache(this);
- }
-
- /**
- * @param ptr Pointer to get lock for.
- * @return Locked lock, must be released in {@code finally} block.
- */
- @SuppressWarnings("LockAcquiredButNotSafelyReleased")
- private static Lock lock(long ptr) {
- assert (ptr & 7) == 0 : ptr; // Unsafe allocated pointers aligned.
-
- Lock l = lock.getLock(ptr >>> 3);
-
- l.lock();
-
- return l;
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("LockAcquiredButNotSafelyReleased")
- @Override protected Value getOffheapValue(int col) {
- GridUnsafeMemory mem = desc.memory();
-
- long p = ptr;
-
- assert p > 0 : p;
-
- byte[] bytes = null;
-
- if (col == KEY_COL) {
- int size = mem.readInt(p + OFFSET_KEY_SIZE);
-
- assert size > 0 : size;
-
- bytes = mem.readBytes(p + OFFSET_KEY, size);
- }
- else if (col == VAL_COL) {
- Lock l = lock(p);
-
- desc.guard().begin();
-
- try {
- long valPtr = mem.readLongVolatile(p + OFFSET_VALUE_REF);
-
- if (valPtr == 0) // Value was evicted.
- return null;
-
- int size = mem.readInt(valPtr);
-
- assert size > 0 : size;
-
- bytes = mem.readBytes(valPtr + OFFSET_VALUE, size);
- }
- finally {
- desc.guard().end();
-
- l.unlock();
- }
- }
- else
- assert false : col;
-
- Data data = Data.create(null, bytes);
-
- return data.readValue();
- }
-
- /** {@inheritDoc} */
- @Override public long pointer() {
- long p = ptr;
-
- assert p > 0: p;
-
- return p;
- }
-
- /** {@inheritDoc} */
- @Override public synchronized void onSwap() throws GridException {
- Lock l = lock(ptr);
-
- try {
- final long p = ptr + OFFSET_VALUE_REF;
-
- final GridUnsafeMemory mem = desc.memory();
-
- final long valPtr = mem.readLongVolatile(p);
-
- assert valPtr > 0: valPtr;
-
- desc.guard().finalizeLater(new Runnable() {
- @Override public void run() {
- mem.casLong(p, valPtr, 0); // If it was unswapped concurrently we will not update.
-
- mem.release(valPtr, mem.readInt(valPtr) + OFFSET_VALUE);
- }
- });
- }
- finally {
- l.unlock();
- }
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod")
- @Override protected Value updateWeakValue(Value exp, Value upd) {
- return exp;
- }
-
- /** {@inheritDoc} */
- @Override public synchronized void onUnswap(Object val) throws GridException {
- super.onUnswap(val);
-
- Value v = getValue(VAL_COL);
-
- byte[] bytes = new byte[SIZE_CALCULATOR.getValueLen(v)];
-
- Data data = Data.create(null, bytes);
-
- data.writeValue(v);
-
- long p = ptr;
-
- assert p > 0 : p;
-
- Lock l = lock(p);
-
- try {
- GridUnsafeMemory mem = desc.memory();
-
- long valPtr = mem.allocate(bytes.length + OFFSET_VALUE);
-
- mem.writeInt(valPtr, bytes.length);
- mem.writeBytes(valPtr + OFFSET_VALUE, bytes);
-
- mem.writeLongVolatile(p + OFFSET_VALUE_REF, valPtr);
- }
- finally {
- l.unlock();
- }
- }
-
- /** {@inheritDoc} */
- @Override protected synchronized Value syncValue() {
- Value v = super.syncValue();
-
- if (v != null)
- return v;
-
- return getOffheapValue(VAL_COL);
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext"})
- @Override public void incrementRefCount() {
- long p = ptr;
-
- GridUnsafeMemory mem = desc.memory();
-
- if (p == 0) { // Serialize data to offheap memory.
- Value key = getValue(KEY_COL);
- Value val = getValue(VAL_COL);
-
- assert key != null;
- assert val != null;
-
- Data data = Data.create(null, new byte[SIZE_CALCULATOR.getValueLen(key)]);
-
- data.writeValue(key);
-
- int keySize = data.length();
-
- p = mem.allocate(keySize + OFFSET_KEY);
-
- // We don't need any synchronization or volatility here because we publish via
- // volatile write to tree node.
- mem.writeInt(p, 1);
- mem.writeLong(p + OFFSET_EXPIRATION, expirationTime);
- mem.writeInt(p + OFFSET_KEY_SIZE, keySize);
- mem.writeBytes(p + OFFSET_KEY, data.getBytes(), 0, keySize);
-
- data = Data.create(null, new byte[SIZE_CALCULATOR.getValueLen(val)]);
-
- data.writeValue(val);
-
- int valSize = data.length();
-
- long valPtr = mem.allocate(valSize + OFFSET_VALUE);
-
- mem.writeInt(valPtr, valSize);
- mem.writeBytes(valPtr + OFFSET_VALUE, data.getBytes(), 0, valSize);
-
- mem.writeLongVolatile(p + OFFSET_VALUE_REF, valPtr);
-
- ptr = p;
-
- desc.cache(this);
- }
- else {
- for (;;) {
- int cnt = mem.readIntVolatile(p);
-
- assert cnt > 0 : cnt;
-
- if (mem.casInt(p, cnt, cnt + 1))
- break;
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override public void decrementRefCount() {
- long p = ptr;
-
- assert p > 0 : p;
-
- GridUnsafeMemory mem = desc.memory();
-
- for (;;) {
- int cnt = mem.readIntVolatile(p);
-
- assert cnt > 0 : cnt;
-
- if (cnt == 1)
- break;
-
- if (mem.casInt(p, cnt, cnt - 1))
- return;
- }
-
- desc.uncache(p);
-
- // Deallocate off-heap memory.
- long valPtr = mem.readLongVolatile(p + OFFSET_VALUE_REF);
-
- assert valPtr >= 0 : valPtr;
-
- if (valPtr != 0)
- mem.release(valPtr, mem.readInt(valPtr) + OFFSET_VALUE);
-
- mem.release(p, mem.readInt(p + OFFSET_KEY_SIZE) + OFFSET_KEY);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOnheap.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOnheap.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOnheap.java
deleted file mode 100644
index 670a97f..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2KeyValueRowOnheap.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-
-import org.apache.ignite.spi.IgniteSpiException;
-import org.h2.value.Value;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Onheap row.
- */
-public class GridH2KeyValueRowOnheap extends GridH2AbstractKeyValueRow {
- /**
- * Constructor.
- *
- * @param desc Row descriptor.
- * @param key Key.
- * @param keyType Key type.
- * @param val Value.
- * @param valType Value type.
- * @param expirationTime Expiration time.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public GridH2KeyValueRowOnheap(GridH2RowDescriptor desc, Object key, int keyType, @Nullable Object val, int valType,
- long expirationTime) throws IgniteSpiException {
- super(desc, key, keyType, val, valType, expirationTime);
- }
-
- /** {@inheritDoc} */
- @Override protected void cache() {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override protected Value getOffheapValue(int col) {
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Row.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Row.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Row.java
deleted file mode 100644
index a326b62..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Row.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.h2.result.*;
-import org.h2.value.*;
-
-/**
- * Row with locking support needed for unique key conflicts resolution.
- */
-public class GridH2Row extends Row implements GridSearchRowPointer {
- /**
- * @param data Column values.
- */
- public GridH2Row(Value... data) {
- super(data, MEMORY_CALCULATE);
- }
-
- /** {@inheritDoc} */
- @Override public long pointer() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public void incrementRefCount() {
- throw new IllegalStateException();
- }
-
- /** {@inheritDoc} */
- @Override public void decrementRefCount() {
- throw new IllegalStateException();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2RowDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2RowDescriptor.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2RowDescriptor.java
deleted file mode 100644
index d7c9aa0..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2RowDescriptor.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import org.apache.ignite.spi.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.spi.indexing.h2.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-import org.jetbrains.annotations.*;
-
-/**
- * Row descriptor.
- */
-public interface GridH2RowDescriptor extends GridOffHeapSmartPointerFactory<GridH2KeyValueRowOffheap> {
- /**
- * @return SPI.
- */
- public GridH2IndexingSpi spi();
-
- /**
- * Creates new row.
- *
- * @param key Key.
- * @param val Value.
- * @param expirationTime Expiration time in millis.
- * @return Row.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public GridH2AbstractKeyValueRow createRow(Object key, @Nullable Object val, long expirationTime)
- throws IgniteSpiException;
-
- /**
- * @param key Cache key.
- * @return Value.
- * @throws GridException If failed.
- */
- public Object readFromSwap(Object key) throws GridException;
-
- /**
- * @return Value type.
- */
- public int valueType();
-
- /**
- * @return {@code true} If we need to store {@code toString()} of value.
- */
- public boolean valueToString();
-
- /**
- * @return Total fields count.
- */
- public int fieldsCount();
-
- /**
- * Gets value type for column index.
- *
- * @param col Column index.
- * @return Value type.
- */
- public int fieldType(int col);
-
- /**
- * Gets column value by column index.
- *
- * @param obj Object to extract value from.
- * @param col Column index.
- * @return Column value.
- */
- public Object columnValue(Object obj, int col);
-
- /**
- * @param col Column index.
- * @return {@code True} if column relates to key, false if it relates to value.
- */
- public boolean isKeyColumn(int col);
-
- /**
- * @return Unsafe memory.
- */
- public GridUnsafeMemory memory();
-
- /**
- * @param row Deserialized offheap row to cache in heap.
- */
- public void cache(GridH2KeyValueRowOffheap row);
-
- /**
- * @param ptr Offheap pointer to remove from cache.
- */
- public void uncache(long ptr);
-
- /**
- * @return Guard.
- */
- public GridUnsafeGuard guard();
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2SpatialIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2SpatialIndex.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2SpatialIndex.java
deleted file mode 100644
index bcd70e7..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2SpatialIndex.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-import com.vividsolutions.jts.geom.*;
-import org.h2.engine.*;
-import org.h2.index.*;
-import org.h2.index.Cursor;
-import org.h2.message.*;
-import org.h2.mvstore.*;
-import org.h2.mvstore.rtree.*;
-import org.h2.result.*;
-import org.h2.table.*;
-import org.h2.value.*;
-
-import java.util.*;
-import java.util.concurrent.locks.*;
-
-/**
- * Spatial index.
- */
-public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex {
- /** */
- private final ReadWriteLock lock = new ReentrantReadWriteLock();
-
- /** */
- private volatile long rowCnt;
-
- /** */
- private long rowIds;
-
- /** */
- private boolean closed;
-
- /** */
- private final MVRTreeMap<Long> treeMap;
-
- /** */
- private final Map<Long, GridH2Row> idToRow = new HashMap<>();
-
- /** */
- private final Map<Value, Long> keyToId = new HashMap<>();
-
- /** */
- private final MVStore store;
-
- /**
- * @param tbl Table.
- * @param idxName Index name.
- * @param cols Columns.
- * @param keyCol Key column.
- * @param valCol Value column.
- */
- public GridH2SpatialIndex(Table tbl, String idxName, IndexColumn[] cols, int keyCol, int valCol) {
- super(keyCol, valCol);
-
- if (cols.length > 1)
- throw DbException.getUnsupportedException("can only do one column");
-
- if ((cols[0].sortType & SortOrder.DESCENDING) != 0)
- throw DbException.getUnsupportedException("cannot do descending");
-
- if ((cols[0].sortType & SortOrder.NULLS_FIRST) != 0)
- throw DbException.getUnsupportedException("cannot do nulls first");
-
- if ((cols[0].sortType & SortOrder.NULLS_LAST) != 0)
- throw DbException.getUnsupportedException("cannot do nulls last");
-
- initBaseIndex(tbl, 0, idxName, cols, IndexType.createNonUnique(false, false, true));
-
- table = tbl;
-
- if (cols[0].column.getType() != Value.GEOMETRY) {
- throw DbException.getUnsupportedException("spatial index on non-geometry column, " +
- cols[0].column.getCreateSQL());
- }
-
- // Index in memory
- store = MVStore.open(null);
- treeMap = store.openMap("spatialIndex", new MVRTreeMap.Builder<Long>());
- }
-
- /**
- * Check closed.
- */
- private void checkClosed() {
- if (closed)
- throw DbException.throwInternalError();
- }
-
- /** {@inheritDoc} */
- @Override public GridH2Row put(GridH2Row row) {
- Lock l = lock.writeLock();
-
- l.lock();
-
- try {
- checkClosed();
-
- Value key = row.getValue(keyCol);
-
- assert key != null;
-
- Long rowId = keyToId.get(key);
-
- if (rowId != null) {
- Long oldRowId = treeMap.remove(getEnvelope(idToRow.get(rowId), rowId));
-
- assert rowId.equals(oldRowId);
- }
- else {
- rowId = ++rowIds;
-
- keyToId.put(key, rowId);
- }
-
- GridH2Row old = idToRow.put(rowId, row);
-
- treeMap.put(getEnvelope(row, rowId), rowId);
-
- if (old == null)
- rowCnt++; // No replace.
-
- return old;
- }
- finally {
- l.unlock();
- }
- }
-
- /**
- * @param row Row.
- * @param rowId Row id.
- * @return Envelope.
- */
- private SpatialKey getEnvelope(SearchRow row, long rowId) {
- Value v = row.getValue(columnIds[0]);
- Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometry();
- Envelope env = g.getEnvelopeInternal();
- return new SpatialKey(rowId,
- (float) env.getMinX(), (float) env.getMaxX(),
- (float) env.getMinY(), (float) env.getMaxY());
- }
-
- /** {@inheritDoc} */
- @Override public GridH2Row remove(SearchRow row) {
- Lock l = lock.writeLock();
-
- l.lock();
-
- try {
- checkClosed();
-
- Value key = row.getValue(keyCol);
-
- assert key != null;
-
- Long rowId = keyToId.remove(key);
-
- assert rowId != null;
-
- GridH2Row oldRow = idToRow.remove(rowId);
-
- assert oldRow != null;
-
- if (!treeMap.remove(getEnvelope(row, rowId), rowId))
- throw DbException.throwInternalError("row not found");
-
- rowCnt--;
-
- return oldRow;
- }
- finally {
- l.unlock();
- }
- }
-
- /** {@inheritDoc} */
- @Override public void close(Session ses) {
- Lock l = lock.writeLock();
-
- l.lock();
-
- try {
- closed = true;
-
- store.close();
- }
- finally {
- l.unlock();
- }
- }
-
- /** {@inheritDoc} */
- @Override protected long getCostRangeIndex(int[] masks, long rowCnt, TableFilter filter, SortOrder sortOrder) {
- rowCnt += Constants.COST_ROW_OFFSET;
- long cost = rowCnt;
- long rows = rowCnt;
-
- if (masks == null)
- return cost;
-
- for (Column column : columns) {
- int idx = column.getColumnId();
- int mask = masks[idx];
- if ((mask & IndexCondition.SPATIAL_INTERSECTS) != 0) {
- cost = 3 + rows / 4;
-
- break;
- }
- }
-
- return cost;
- }
-
- /** {@inheritDoc} */
- @Override public double getCost(Session ses, int[] masks, TableFilter filter, SortOrder sortOrder) {
- return getCostRangeIndex(masks, rowCnt, filter, sortOrder);
- }
-
- /** {@inheritDoc} */
- @Override public Cursor find(Session ses, SearchRow first, SearchRow last) {
- Lock l = lock.readLock();
-
- l.lock();
-
- try {
- checkClosed();
-
- return new GridH2Cursor(rowIterator(treeMap.keySet().iterator()));
- }
- finally {
- l.unlock();
- }
- }
-
- /** {@inheritDoc} */
- @Override public boolean canGetFirstOrLast() {
- return true;
- }
-
- /**
- * @param i Spatial key iterator.
- * @return Iterator over rows.
- */
- private Iterator<GridH2Row> rowIterator(Iterator<SpatialKey> i) {
- if (!i.hasNext())
- return Collections.emptyIterator();
-
- List<GridH2Row> rows = new ArrayList<>();
-
- do {
- GridH2Row row = idToRow.get(i.next().getId());
-
- assert row != null;
-
- rows.add(row);
- }
- while (i.hasNext());
-
- return filter(rows.iterator());
- }
-
- /** {@inheritDoc} */
- @Override public Cursor findFirstOrLast(Session ses, boolean first) {
- Lock l = lock.readLock();
-
- l.lock();
-
- try {
- checkClosed();
-
- if (!first)
- throw DbException.throwInternalError("Spatial Index can only be fetch by ascending order");
-
- Iterator<GridH2Row> iter = rowIterator(treeMap.keySet().iterator());
-
- return new SingleRowCursor(iter.hasNext() ? iter.next() : null);
- }
- finally {
- l.unlock();
- }
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCount(Session ses) {
- return rowCnt;
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCountApproximation() {
- return rowCnt;
- }
-
- /** {@inheritDoc} */
- @Override public Cursor findByGeometry(TableFilter filter, SearchRow intersection) {
- Lock l = lock.readLock();
-
- l.lock();
-
- try {
- if (intersection == null)
- return find(filter.getSession(), null, null);
-
- return new GridH2Cursor(rowIterator(treeMap.findIntersectingKeys(getEnvelope(intersection, 0))));
- }
- finally {
- l.unlock();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Table.java
deleted file mode 100644
index 65a3571..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/opt/GridH2Table.java
+++ /dev/null
@@ -1,893 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2.opt;
-
-
-import org.apache.ignite.spi.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-import org.h2.api.*;
-import org.h2.command.ddl.*;
-import org.h2.engine.*;
-import org.h2.index.*;
-import org.h2.message.*;
-import org.h2.result.*;
-import org.h2.schema.*;
-import org.h2.table.*;
-import org.jdk8.backport.*;
-import org.jetbrains.annotations.*;
-
-import java.sql.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.locks.*;
-
-/**
- * H2 Table implementation.
- */
-public class GridH2Table extends TableBase {
- /** */
- private final String spaceName;
-
- /** */
- private final GridH2RowDescriptor desc;
-
- /** */
- private final ArrayList<Index> idxs;
-
- /** */
- private final ReadWriteLock lock;
-
- /** */
- private final Set<Session> sessions = Collections.newSetFromMap(new ConcurrentHashMap8<Session, Boolean>());
-
- /** */
- private volatile Object[] actualSnapshot;
-
- /** */
- private final long writeLockWaitTime;
-
- /**
- * Creates table.
- *
- * @param createTblData Table description.
- * @param desc Row descriptor.
- * @param idxsFactory Indexes factory.
- * @param spaceName Space name.
- */
- public GridH2Table(CreateTableData createTblData, @Nullable GridH2RowDescriptor desc, IndexesFactory idxsFactory,
- @Nullable String spaceName) {
- super(createTblData);
-
- assert idxsFactory != null;
-
- this.desc = desc;
- this.spaceName = spaceName;
-
- writeLockWaitTime = desc == null ? 100 : desc.spi().getIndexWriteLockWaitTime();
-
- assert writeLockWaitTime > 0 : writeLockWaitTime;
-
- idxs = idxsFactory.createIndexes(this);
-
- assert idxs != null;
- assert idxs.size() >= 1;
-
- lock = new ReentrantReadWriteLock();
-
- // Add scan index at 0 which is required by H2.
- idxs.add(0, new ScanIndex(index(0)));
- }
-
- /** {@inheritDoc} */
- @Override public long getDiskSpaceUsed() {
- return 0;
- }
-
- /**
- * @return Row descriptor.
- */
- public GridH2RowDescriptor rowDescriptor() {
- return desc;
- }
-
- /**
- * Should be called when entry is swapped.
- *
- * @param key Entry key.
- * @return {@code true} If row was found.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public boolean onSwap(Object key) throws GridException {
- return onSwapUnswap(key, null);
- }
-
- /**
- * Should be called when entry is unswapped.
- *
- * @param key Key.
- * @param val Value.
- * @return {@code true} If row was found.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public boolean onUnswap(Object key, Object val) throws GridException {
- assert val != null : "Key=" + key;
-
- return onSwapUnswap(key, val);
- }
-
- /**
- * Swaps or unswaps row.
- *
- * @param key Key.
- * @param val Value for promote or {@code null} if we have to swap.
- * @return {@code true} if row was found and swapped/unswapped.
- * @throws GridException If failed.
- */
- @SuppressWarnings("LockAcquiredButNotSafelyReleased")
- private boolean onSwapUnswap(Object key, @Nullable Object val) throws GridException {
- assert key != null;
-
- GridH2TreeIndex pk = pk();
-
- GridH2AbstractKeyValueRow row = desc.createRow(key, null, 0); // Create search row.
-
- GridUnsafeMemory mem = desc.memory();
-
- lock.readLock().lock();
-
- if (mem != null)
- desc.guard().begin();
-
- try {
- row = pk.findOne(row);
-
- if (row == null)
- return false;
-
- if (val == null)
- row.onSwap();
- else
- row.onUnswap(val);
-
- return true;
- }
- finally {
- lock.readLock().unlock();
-
- if (mem != null)
- desc.guard().end();
- }
- }
-
- /**
- * @return Space name.
- */
- @Nullable String spaceName() {
- return spaceName;
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings({"LockAcquiredButNotSafelyReleased", "SynchronizationOnLocalVariableOrMethodParameter", "unchecked"})
- @Override public void lock(@Nullable final Session ses, boolean exclusive, boolean force) {
- if (ses != null) {
- if (!sessions.add(ses))
- return;
-
- synchronized (ses) {
- ses.addLock(this);
- }
- }
-
- Object[] snapshot;
-
- for (long waitTime = writeLockWaitTime;; waitTime *= 2) { // Increase wait time to avoid starvation.
- snapshot = actualSnapshot;
-
- if (snapshot != null) {
- // Reuse existing snapshot without locking.
- for (int i = 1, len = idxs.size(); i < len; i++)
- index(i).takeSnapshot(snapshot[i - 1]);
-
- return;
- }
-
- try {
- if (lock.writeLock().tryLock(waitTime, TimeUnit.MILLISECONDS))
- break;
- }
- catch (InterruptedException e) {
- throw new GridRuntimeException("Thread got interrupted while trying to acquire index lock.", e);
- }
- }
-
- boolean snapshoted = false;
-
- try {
- snapshot = actualSnapshot; // Try again inside of the lock.
-
- if (snapshot == null) {
- snapshot = takeIndexesSnapshot();
-
- if (desc == null || desc.memory() == null) // This optimization is disabled for off-heap index.
- actualSnapshot = snapshot;
-
- snapshoted = true;
- }
- }
- finally {
- lock.writeLock().unlock();
- }
-
- if (!snapshoted) {
- for (int i = 1, len = idxs.size(); i < len; i++)
- index(i).takeSnapshot(snapshot[i - 1]);
- }
- }
-
- /**
- * Must be called inside of write lock because when using multiple indexes we have to ensure that all of them have
- * the same contents at snapshot taking time.
- *
- * @return New indexes data snapshot.
- */
- @SuppressWarnings("unchecked")
- private Object[] takeIndexesSnapshot() {
- int len = idxs.size();
-
- Object[] snapshot = new ConcurrentNavigableMap[len - 1];
-
- for (int i = 1; i < len; i++) { // Take snapshots on all except first which is scan.
- Object s = index(i).takeSnapshot(null);
-
- snapshot[i - 1] = s;
- }
-
- return snapshot;
- }
-
- /** {@inheritDoc} */
- @Override public void close(Session ses) {
- assert !sessions.contains(ses);
- }
-
- /** {@inheritDoc} */
- @Override public void unlock(@Nullable Session ses) {
- if (ses != null) {
- boolean res = sessions.remove(ses);
-
- assert res;
- }
-
- for (int i = 1, len = idxs.size(); i < len; i++) // Release snapshots on all except first which is scan.
- index(i).releaseSnapshot();
- }
-
- /**
- * Closes table and releases resources.
- */
- public void close() {
- Lock l = lock.writeLock();
-
- l.lock();
-
- try {
- for (int i = 1, len = idxs.size(); i < len; i++)
- index(i).close(null);
- }
- finally {
- l.unlock();
- }
- }
-
- /**
- * Updates table for given key. If value is null then row with given key will be removed from table,
- * otherwise value and expiration time will be updated or new row will be added.
- *
- * @param key Key.
- * @param val Value.
- * @param expirationTime Expiration time.
- * @return {@code True} if operation succeeded.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public boolean update(Object key, @Nullable Object val, long expirationTime) throws IgniteSpiException {
- GridH2Row row = desc.createRow(key, val, expirationTime);
-
- return doUpdate(row, val == null);
- }
-
- /**
- * Gets index by index.
- *
- * @param idx Index in list.
- * @return Index.
- */
- private GridH2IndexBase index(int idx) {
- return (GridH2IndexBase)idxs.get(idx);
- }
-
- /**
- * Gets primary key.
- *
- * @return Primary key.
- */
- private GridH2TreeIndex pk() {
- return (GridH2TreeIndex)idxs.get(1);
- }
-
- /**
- * For testing only.
- *
- * @param row Row.
- * @param del If given row should be deleted from table.
- * @return {@code True} if operation succeeded.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- @SuppressWarnings("LockAcquiredButNotSafelyReleased")
- boolean doUpdate(GridH2Row row, boolean del) throws IgniteSpiException {
- // Here we assume that each key can't be updated concurrently and case when different indexes
- // getting updated from different threads with different rows with the same key is impossible.
- GridUnsafeMemory mem = desc == null ? null : desc.memory();
-
- lock.readLock().lock();
-
- if (mem != null)
- desc.guard().begin();
-
- try {
- GridH2TreeIndex pk = pk();
-
- if (!del) {
- GridH2Row old = pk.put(row); // Put to PK.
-
- int len = idxs.size();
-
- int i = 1;
-
- // Put row if absent to all indexes sequentially.
- // Start from 2 because 0 - Scan (don't need to update), 1 - PK (already updated).
- while (++i < len) {
- GridH2IndexBase idx = index(i);
-
- assert !idx.getIndexType().isUnique() : "Unique indexes are not supported.";
-
- GridH2Row old2 = idx.put(row);
-
- if (old2 != null) { // Row was replaced in index.
- if (!eq(pk, old2, old))
- throw new IllegalStateException("Row conflict should never happen, unique indexes are " +
- "not supported.");
- }
- else if (old != null) // Row was not replaced, need to remove manually.
- idx.remove(old);
- }
- }
- else {
- // index(1) is PK, get full row from there (search row here contains only key but no other columns).
- row = pk.remove(row);
-
- if (row != null) {
- // Remove row from all indexes.
- // Start from 2 because 0 - Scan (don't need to update), 1 - PK (already updated).
- for (int i = 2, len = idxs.size(); i < len; i++) {
- Row res = index(i).remove(row);
-
- assert eq(pk, res, row): "\n" + row + "\n" + res;
- }
- }
- else
- return false;
- }
-
- // The snapshot is not actual after update.
- actualSnapshot = null;
-
- return true;
- }
- finally {
- lock.readLock().unlock();
-
- if (mem != null)
- desc.guard().end();
- }
- }
-
- /**
- * Check row equality.
- *
- * @param pk Primary key index.
- * @param r1 First row.
- * @param r2 Second row.
- * @return {@code true} if rows are the same.
- */
- private static boolean eq(Index pk, SearchRow r1, SearchRow r2) {
- return r1 == r2 || (r1 != null && r2 != null && pk.compareRows(r1, r2) == 0);
- }
-
- /**
- * For testing only.
- *
- * @return Indexes.
- */
- ArrayList<GridH2IndexBase> indexes() {
- ArrayList<GridH2IndexBase> res = new ArrayList<>(idxs.size() - 1);
-
- for (int i = 1, len = idxs.size(); i < len ; i++)
- res.add(index(i));
-
- return res;
- }
-
- /**
- * Rebuilds all indexes of this table.
- */
- public void rebuildIndexes() {
- GridUnsafeMemory memory = desc == null ? null : desc.memory();
-
- lock.writeLock().lock();
-
- try {
- if (memory == null && actualSnapshot == null)
- actualSnapshot = takeIndexesSnapshot(); // Allow read access while we are rebuilding indexes.
-
- for (int i = 1, len = idxs.size(); i < len; i++) {
- GridH2IndexBase newIdx = index(i).rebuild();
-
- idxs.set(i, newIdx);
-
- if (i == 1) // ScanIndex at 0 and actualSnapshot can contain references to old indexes, reset them.
- idxs.set(0, new ScanIndex(newIdx));
- }
- }
- catch (InterruptedException ignored) {
- // No-op.
- }
- finally {
- lock.writeLock().unlock();
-
- actualSnapshot = null;
- }
- }
-
- /** {@inheritDoc} */
- @Override public Index addIndex(Session ses, String s, int i, IndexColumn[] idxCols, IndexType idxType,
- boolean b, String s1) {
- throw DbException.getUnsupportedException("addIndex");
- }
-
- /** {@inheritDoc} */
- @Override public void removeRow(Session ses, Row row) {
- throw DbException.getUnsupportedException("removeRow");
- }
-
- /** {@inheritDoc} */
- @Override public void truncate(Session ses) {
- throw DbException.getUnsupportedException("truncate");
- }
-
- /** {@inheritDoc} */
- @Override public void addRow(Session ses, Row row) {
- throw DbException.getUnsupportedException("addRow");
- }
-
- /** {@inheritDoc} */
- @Override public void checkSupportAlter() {
- throw DbException.getUnsupportedException("alter");
- }
-
- /** {@inheritDoc} */
- @Override public String getTableType() {
- return EXTERNAL_TABLE_ENGINE;
- }
-
- /** {@inheritDoc} */
- @Override public Index getScanIndex(Session ses) {
- return getIndexes().get(0); // Scan must be always first index.
- }
-
- /** {@inheritDoc} */
- @Override public Index getUniqueIndex() {
- return getIndexes().get(1); // PK index is always second.
- }
-
- /** {@inheritDoc} */
- @Override public ArrayList<Index> getIndexes() {
- return idxs;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isLockedExclusively() {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isLockedExclusivelyBy(Session ses) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public long getMaxDataModificationId() {
- return 0;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isDeterministic() {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public boolean canGetRowCount() {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public boolean canDrop() {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCount(@Nullable Session ses) {
- return getUniqueIndex().getRowCount(ses);
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCountApproximation() {
- return getUniqueIndex().getRowCountApproximation();
- }
-
- /** {@inheritDoc} */
- @Override public void checkRename() {
- throw DbException.getUnsupportedException("rename");
- }
-
- /**
- * Creates index column for table.
- *
- * @param col Column index.
- * @param sorting Sorting order {@link SortOrder}
- * @return Created index column.
- */
- public IndexColumn indexColumn(int col, int sorting) {
- IndexColumn res = new IndexColumn();
-
- res.column = getColumn(col);
- res.columnName = res.column.getName();
- res.sortType = sorting;
-
- return res;
- }
-
- /**
- * H2 Table engine.
- */
- @SuppressWarnings({"PublicInnerClass", "FieldAccessedSynchronizedAndUnsynchronized"})
- public static class Engine implements TableEngine {
- /** */
- private static GridH2RowDescriptor rowDesc;
-
- /** */
- private static IndexesFactory idxsFactory;
-
- /** */
- private static GridH2Table resTbl;
-
- /** */
- private static String spaceName;
-
- /** {@inheritDoc} */
- @Override public TableBase createTable(CreateTableData createTblData) {
- resTbl = new GridH2Table(createTblData, rowDesc, idxsFactory, spaceName);
-
- return resTbl;
- }
-
- /**
- * Creates table using given connection, DDL clause for given type descriptor and list of indexes.
- *
- * @param conn Connection.
- * @param sql DDL clause.
- * @param desc Row descriptor.
- * @param factory Indexes factory.
- * @param space Space name.
- * @throws SQLException If failed.
- * @return Created table.
- */
- public static synchronized GridH2Table createTable(Connection conn, String sql,
- @Nullable GridH2RowDescriptor desc, IndexesFactory factory, String space)
- throws SQLException {
- rowDesc = desc;
- idxsFactory = factory;
- spaceName = space;
-
- try {
- try (Statement s = conn.createStatement()) {
- s.execute(sql + " engine \"" + Engine.class.getName() + "\"");
- }
-
- return resTbl;
- }
- finally {
- resTbl = null;
- idxsFactory = null;
- rowDesc = null;
- }
- }
- }
-
- /**
- * Type which can create indexes list for given table.
- */
- @SuppressWarnings({"PackageVisibleInnerClass", "PublicInnerClass"})
- public static interface IndexesFactory {
- /**
- * Create list of indexes. First must be primary key, after that all unique indexes and
- * only then non-unique indexes.
- * All indexes must be subtypes of {@link GridH2TreeIndex}.
- *
- * @param tbl Table to create indexes for.
- * @return List of indexes.
- */
- ArrayList<Index> createIndexes(GridH2Table tbl);
- }
-
- /**
- * Wrapper type for primary key.
- */
- @SuppressWarnings("PackageVisibleInnerClass")
- static class ScanIndex implements Index {
- /** */
- static final String SCAN_INDEX_NAME_SUFFIX = "__SCAN_";
-
- /** */
- private static final IndexType TYPE = IndexType.createScan(false);
-
- /** */
- private final GridH2IndexBase delegate;
-
- /**
- * Constructor.
- *
- * @param delegate Index delegate to.
- */
- private ScanIndex(GridH2IndexBase delegate) {
- this.delegate = delegate;
- }
-
- /** {@inheritDoc} */
- @Override public long getDiskSpaceUsed() {
- return 0;
- }
-
- /** {@inheritDoc} */
- @Override public void add(Session ses, Row row) {
- delegate.add(ses, row);
- }
-
- /** {@inheritDoc} */
- @Override public boolean canFindNext() {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public boolean canGetFirstOrLast() {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public boolean canScan() {
- return delegate.canScan();
- }
-
- /** {@inheritDoc} */
- @Override public void close(Session ses) {
- delegate.close(ses);
- }
-
- /** {@inheritDoc} */
- @Override public void commit(int operation, Row row) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public int compareRows(SearchRow rowData, SearchRow compare) {
- return delegate.compareRows(rowData, compare);
- }
-
- /** {@inheritDoc} */
- @Override public Cursor find(TableFilter filter, SearchRow first, SearchRow last) {
- return find(filter.getSession(), first, last);
- }
-
- /** {@inheritDoc} */
- @Override public Cursor find(Session ses, SearchRow first, SearchRow last) {
- return delegate.find(ses, null, null);
- }
-
- /** {@inheritDoc} */
- @Override public Cursor findFirstOrLast(Session ses, boolean first) {
- throw DbException.getUnsupportedException("SCAN");
- }
-
- /** {@inheritDoc} */
- @Override public Cursor findNext(Session ses, SearchRow higherThan, SearchRow last) {
- throw DbException.throwInternalError();
- }
-
- /** {@inheritDoc} */
- @Override public int getColumnIndex(Column col) {
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override public Column[] getColumns() {
- return delegate.getColumns();
- }
-
- /** {@inheritDoc} */
- @Override public double getCost(Session ses, int[] masks, TableFilter tblFilter, SortOrder sortOrder) {
- return getRowCountApproximation() + Constants.COST_ROW_OFFSET;
- }
-
- /** {@inheritDoc} */
- @Override public IndexColumn[] getIndexColumns() {
- return delegate.getIndexColumns();
- }
-
- /** {@inheritDoc} */
- @Override public IndexType getIndexType() {
- return TYPE;
- }
-
- /** {@inheritDoc} */
- @Override public String getPlanSQL() {
- return delegate.getTable().getSQL() + "." + SCAN_INDEX_NAME_SUFFIX;
- }
-
- /** {@inheritDoc} */
- @Override public Row getRow(Session ses, long key) {
- return delegate.getRow(ses, key);
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCount(Session ses) {
- return delegate.getRowCount(ses);
- }
-
- /** {@inheritDoc} */
- @Override public long getRowCountApproximation() {
- return delegate.getRowCountApproximation();
- }
-
- /** {@inheritDoc} */
- @Override public Table getTable() {
- return delegate.getTable();
- }
-
- /** {@inheritDoc} */
- @Override public boolean isRowIdIndex() {
- return delegate.isRowIdIndex();
- }
-
- /** {@inheritDoc} */
- @Override public boolean needRebuild() {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override public void remove(Session ses) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void remove(Session ses, Row row) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void setSortedInsertMode(boolean sortedInsertMode) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void truncate(Session ses) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public Schema getSchema() {
- return delegate.getSchema();
- }
-
- /** {@inheritDoc} */
- @Override public boolean isHidden() {
- return delegate.isHidden();
- }
-
- /** {@inheritDoc} */
- @Override public void checkRename() {
- throw DbException.getUnsupportedException("rename");
- }
-
- /** {@inheritDoc} */
- @Override public ArrayList<DbObject> getChildren() {
- return delegate.getChildren();
- }
-
- /** {@inheritDoc} */
- @Override public String getComment() {
- return delegate.getComment();
- }
-
- /** {@inheritDoc} */
- @Override public String getCreateSQL() {
- return null; // Scan should return null.
- }
-
- /** {@inheritDoc} */
- @Override public String getCreateSQLForCopy(Table tbl, String quotedName) {
- return delegate.getCreateSQLForCopy(tbl, quotedName);
- }
-
- /** {@inheritDoc} */
- @Override public Database getDatabase() {
- return delegate.getDatabase();
- }
-
- /** {@inheritDoc} */
- @Override public String getDropSQL() {
- return delegate.getDropSQL();
- }
-
- /** {@inheritDoc} */
- @Override public int getId() {
- return delegate.getId();
- }
-
- /** {@inheritDoc} */
- @Override public String getName() {
- return delegate.getName() + SCAN_INDEX_NAME_SUFFIX;
- }
-
- /** {@inheritDoc} */
- @Override public String getSQL() {
- return delegate.getSQL();
- }
-
- /** {@inheritDoc} */
- @Override public int getType() {
- return delegate.getType();
- }
-
- /** {@inheritDoc} */
- @Override public boolean isTemporary() {
- return delegate.isTemporary();
- }
-
- /** {@inheritDoc} */
- @Override public void removeChildrenAndResources(Session ses) {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void rename(String newName) {
- throw DbException.getUnsupportedException("rename");
- }
-
- /** {@inheritDoc} */
- @Override public void setComment(String comment) {
- throw DbException.getUnsupportedException("comment");
- }
-
- /** {@inheritDoc} */
- @Override public void setTemporary(boolean temporary) {
- throw DbException.getUnsupportedException("temporary");
- }
- }
-}
[05/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpi.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpi.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpi.java
deleted file mode 100644
index 9d42582..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpi.java
+++ /dev/null
@@ -1,2398 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
-* __ ____/___________(_)______ /__ ____/______ ____(_)_______
-* _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
-* / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
-* \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
-*/
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.apache.ignite.*;
-import org.apache.ignite.marshaller.*;
-import org.apache.ignite.resources.*;
-import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.indexing.*;
-import org.gridgain.grid.*;
-import org.gridgain.grid.cache.query.*;
-import org.gridgain.grid.spi.indexing.h2.opt.*;
-import org.gridgain.grid.util.*;
-import org.gridgain.grid.util.offheap.unsafe.*;
-import org.gridgain.grid.util.typedef.*;
-import org.gridgain.grid.util.typedef.internal.*;
-import org.h2.api.*;
-import org.h2.command.*;
-import org.h2.constant.*;
-import org.h2.index.*;
-import org.h2.jdbc.*;
-import org.h2.message.*;
-import org.h2.mvstore.cache.*;
-import org.h2.server.web.*;
-import org.h2.table.*;
-import org.h2.tools.*;
-import org.h2.util.*;
-import org.h2.value.*;
-import org.jdk8.backport.*;
-import org.jetbrains.annotations.*;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.math.*;
-import java.sql.*;
-import java.text.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import static org.apache.ignite.IgniteSystemProperties.*;
-import static org.apache.ignite.spi.indexing.IndexType.*;
-import static org.gridgain.grid.spi.indexing.h2.opt.GridH2AbstractKeyValueRow.*;
-import static org.h2.result.SortOrder.*;
-
-/**
- * Indexing SPI implementation based on H2 database engine. In this implementation main query language is SQL,
- * fulltext indexing can be performed using Lucene or using embedded H2 mechanism. For each registered space
- * the SPI will create respective schema, for default space (where space name is null) schema
- * with name {@code PUBLIC} will be used. To avoid name conflicts user should not explicitly name
- * a schema {@code PUBLIC}.
- * <p>
- * For each registered {@link org.apache.ignite.spi.indexing.IndexingTypeDescriptor} this SPI will create respective SQL table with
- * {@code '_key'} and {@code '_val'} fields for key and value, and fields from
- * {@link org.apache.ignite.spi.indexing.IndexingTypeDescriptor#keyFields()} and {@link org.apache.ignite.spi.indexing.IndexingTypeDescriptor#valueFields()}.
- * For each table it will create indexes declared in {@link org.apache.ignite.spi.indexing.IndexingTypeDescriptor#indexes()}.
- * <p>
- * Note that you can monitor longer queries by setting {@link #setLongQueryExplain(boolean)} to {@code true}.
- * In this case a warning and execution plan are printed out if query exceeds certain time threshold. The
- * time threshold for long queries is configured via {@link #setLongQueryExecutionTimeout(long)} parameter.
- * <h1 class="header">Configuration</h1>
- * <h2 class="header">Mandatory</h2>
- * This SPI has no mandatory configuration parameters.
- * <h2 class="header">Optional</h2>
- * The following configuration parameters are optional:
- * <ul>
- * <li>Whether SPI will convert key type to SQL type or store keys in binary form
- * (see {@link #setDefaultIndexFixedTyping(boolean)})</li>
- * <li>Whether SPI will create tables for each primitive key-value pair
- * (see {@link #setDefaultIndexPrimitiveKey(boolean)})</li>
- * <li>Whether SPI will create indexes for each primitive value
- * (see {@link #setDefaultIndexPrimitiveValue(boolean)})</li>
- * <li>Search path for SQL objects (see {@link #setSearchPath(String...)})</li>
- * <li>Off-heap memory (see {@link #setMaxOffHeapMemory(long)})</li>
- * <li>Deserialized off-heap rows cache size (see {@link #setMaxOffheapRowsCacheSize(int)})</li>
- * <li>Name (see {@link #setName(String)})</li>
- * <li>SPI will issue a warning if query execution takes longer than specified period in milliseconds (see
- * {@link #setLongQueryExecutionTimeout(long)})</li>
- * <li>Whether SPI will print execution plan for slow queries (see {@link #setLongQueryExplain(boolean)})</li>
- * <li>Classes containing user defined functions (see {@link #setIndexCustomFunctionClasses(Class[])})</li>
- * <li>Per-space configurations (see {@link #setSpaceConfigurations(GridH2IndexingSpaceConfiguration...)})</li>
- * </ul>
- * <h1 class="header">Some important defaults.</h1>
- * <ul>
- * <li>All the data will be kept in memory</li>
- * <li>Primitive types will not be indexed (e.g. java types which can be directly converted to SQL types)</li>
- * <li>
- * Key types will be converted to SQL types, so it is impossible to store one value type with
- * different key types
- * </li>
- * </ul>
- * Here is a Java example on how to configure grid with {@code GridH2IndexingSpi}.
- * <pre name="code" class="java">
- * GridH2IndexingSpi spi = new GridH2IndexingSpi();
- *
- * // Set SPI name.
- * spi.setName(name);
- *
- * spi.setDefaultIndexPrimitiveKey(true);
- * spi.setDefaultIndexPrimitiveValue(true);
- *
- * GridConfiguration cfg = new GridConfiguration();
- *
- * // Overrides default indexing SPI.
- * cfg.setIndexingSpi(spi);
- *
- * // Starts grid.
- * G.start(cfg);
- * </pre>
- * Here is an example of how to configure {@code GridH2IndexingSpi} from Spring XML configuration file.
- * <pre name="code" class="xml">
- * <property name="indexingSpi">
- * <list>
- * <bean class="org.gridgain.grid.spi.indexing.h2.GridH2IndexingSpi">
- * <!-- Index primitives. -->
- * <property name="defaultIndexPrimitiveKey" value="true"/>
- *
- * <!-- Allow different key types for one value type. -->
- * <property name="defaultIndexFixedTyping" value="false"/>
- * </bean>
- * </list>
- * </property>
- * </pre>
- * <p>
- * <img src="http://www.gridgain.com/images/spring-small.png">
- * <br>
- * For information about Spring framework visit <a href="http://www.springframework.org/">www.springframework.org</a>
- * @see org.apache.ignite.spi.indexing.IndexingSpi
- */
-@IgniteSpiMultipleInstancesSupport(true)
-@SuppressWarnings({"UnnecessaryFullyQualifiedName", "NonFinalStaticVariableUsedInClassInitialization"})
-public class GridH2IndexingSpi extends IgniteSpiAdapter implements IndexingSpi, GridH2IndexingSpiMBean {
- /** Default query execution time interpreted as long query (3 seconds). */
- public static final long DFLT_LONG_QRY_EXEC_TIMEOUT = 3000;
-
- /** Default index write lock wait time in milliseconds. */
- private static final long DFLT_IDX_WRITE_LOCK_WAIT_TIME = 100;
-
- /** Default value for {@link #setUseOptimizedSerializer(boolean)} flag. */
- public static final boolean DFLT_USE_OPTIMIZED_SERIALIZER = true;
-
- /** Default DB name. */
- private static final String DFLT_DB_NAME = "gridgain_indexes";
-
- /** Default DB options. */
- private static final String DFLT_DB_OPTIONS = ";LOCK_MODE=3;MULTI_THREADED=1;DB_CLOSE_ON_EXIT=FALSE" +
- ";DEFAULT_LOCK_TIMEOUT=10000";
-
- /** Options for optimized mode to work properly. */
- private static final String OPTIMIZED_DB_OPTIONS = ";OPTIMIZE_REUSE_RESULTS=0;QUERY_CACHE_SIZE=0;" +
- "RECOMPILE_ALWAYS=1;MAX_OPERATION_MEMORY=0";
-
- /** Field name for key. */
- public static final String KEY_FIELD_NAME = "_key";
-
- /** Field name for value. */
- public static final String VAL_FIELD_NAME = "_val";
-
- /** */
- private static final Field COMMAND_FIELD;
-
- /**
- * Command in H2 prepared statement.
- */
- static {
- try {
- COMMAND_FIELD = JdbcPreparedStatement.class.getDeclaredField("command");
-
- COMMAND_FIELD.setAccessible(true);
- }
- catch (NoSuchFieldException e) {
- throw new IllegalStateException("Check H2 version in classpath.", e);
- }
- }
-
- /** */
- private static final ThreadLocal<GridH2IndexingSpi> localSpi = new ThreadLocal<>();
-
- /** */
- private Class<?>[] idxCustomFuncClss;
-
- /** */
- private String[] searchPath;
-
- /** */
- private volatile String cachedSearchPathCmd;
-
- /** */
- private String initScriptPath;
-
- /** */
- private boolean dfltIdxPrimitiveKey;
-
- /** */
- private boolean dfltIdxPrimitiveVal;
-
- /** */
- private boolean dfltIdxFixedTyping = true;
-
- /** */
- private long maxOffHeapMemory = -1;
-
- /** */
- private long longQryExecTimeout = DFLT_LONG_QRY_EXEC_TIMEOUT;
-
- /** */
- private long idxWriteLockWaitTime = DFLT_IDX_WRITE_LOCK_WAIT_TIME;
-
- /** */
- private boolean longQryExplain;
-
- /** */
- private boolean dfltEscapeAll;
-
- /** */
- private boolean useOptimizedSerializer = DFLT_USE_OPTIMIZED_SERIALIZER;
-
- /** Cache for deserialized offheap rows. */
- private CacheLongKeyLIRS<GridH2KeyValueRowOffheap> rowCache = new CacheLongKeyLIRS<>(32 * 1024, 1, 128, 256);
-
- /** */
- private Map<String, GridH2IndexingSpaceConfiguration> spaceCfgs =
- new LinkedHashMap<>();
-
- /** Logger. */
- @IgniteLoggerResource
- private IgniteLogger log;
-
- /** Node ID. */
- @IgniteLocalNodeIdResource
- private UUID nodeId;
-
- /** */
- @IgniteMarshallerResource
- private IgniteMarshaller igniteMarshaller;
-
- /** */
- private final CountDownLatch ctxInitLatch = new CountDownLatch(1);
-
- /** Marshaller. */
- private IndexingMarshaller marshaller;
-
- /** */
- private GridUnsafeMemory offheap;
-
- /** */
- private final Collection<String> schemaNames = new GridConcurrentHashSet<>();
-
- /** Collection of schemaNames and registered tables. */
- private final ConcurrentMap<String, Schema> schemas = new ConcurrentHashMap8<>();
-
- /** */
- private String dbUrl = "jdbc:h2:mem:";
-
- /** */
- private final Collection<Connection> conns = Collections.synchronizedCollection(new ArrayList<Connection>());
-
- /** */
- private ThreadLocal<ConnectionWrapper> connCache = new ThreadLocal<ConnectionWrapper>() {
- @Nullable @Override public ConnectionWrapper get() {
- ConnectionWrapper c = super.get();
-
- boolean reconnect = true;
-
- try {
- reconnect = c == null || c.connection().isClosed();
- }
- catch (SQLException e) {
- U.warn(log, "Failed to check connection status.", e);
- }
-
- if (reconnect) {
- c = initialValue();
-
- set(c);
- }
-
- return c;
- }
-
- @Nullable @Override protected ConnectionWrapper initialValue() {
- Connection c = null;
-
- try {
- c = DriverManager.getConnection(dbUrl);
-
- if (!F.isEmpty(searchPath)) {
- try (Statement s = c.createStatement()) {
- String cmd = cachedSearchPathCmd;
-
- if (cmd == null) {
- SB b = new SB("SET SCHEMA_SEARCH_PATH ");
-
- for (int i = 0; i < searchPath.length; i++) {
- if (i != 0)
- b.a(',');
-
- b.a('"').a(schema(searchPath[i])).a('"');
- }
-
- cachedSearchPathCmd = cmd = b.toString();
- }
-
- s.executeUpdate(cmd);
- }
- }
-
- conns.add(c);
-
- return new ConnectionWrapper(c);
- }
- catch (SQLException e) {
- U.close(c, log);
-
- throw new GridRuntimeException("Failed to initialize DB connection: " + dbUrl, e);
- }
- }
- };
-
- /**
- * Gets DB connection.
- *
- * @param schema Whether to set schema for connection or not.
- * @return DB connection.
- * @throws org.apache.ignite.spi.IgniteSpiException In case of error.
- */
- private Connection connectionForThread(@Nullable String schema) throws IgniteSpiException {
- ConnectionWrapper c = connCache.get();
-
- if (c == null)
- throw new IgniteSpiException("Failed to get DB connection for thread (check log for details).");
-
- if (schema != null && !F.eq(c.schema(), schema)) {
- Statement stmt = null;
-
- try {
- stmt = c.connection().createStatement();
-
- stmt.executeUpdate("SET SCHEMA \"" + schema + '"');
-
- if (log.isDebugEnabled())
- log.debug("Initialized H2 schema for queries on space: " + schema);
-
- c.schema(schema);
- }
- catch (SQLException e) {
- throw new IgniteSpiException("Failed to set schema for DB connection for thread [schema=" +
- schema + "]", e);
- }
- finally {
- U.close(stmt, log);
- }
- }
-
- return c.connection();
- }
-
- /**
- * Creates DB schema if it has not been created yet.
- *
- * @param schema Schema name.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed to create db schema.
- */
- private void createSchemaIfAbsent(String schema) throws IgniteSpiException {
- executeStatement("CREATE SCHEMA IF NOT EXISTS \"" + schema + '"');
-
- if (log.isDebugEnabled())
- log.debug("Created H2 schema for index database: " + schema);
- }
-
- /**
- * @param sql SQL statement.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private void executeStatement(String sql) throws IgniteSpiException {
- Statement stmt = null;
-
- try {
- Connection c = connectionForThread(null);
-
- stmt = c.createStatement();
-
- stmt.executeUpdate(sql);
- }
- catch (SQLException e) {
- onSqlException();
-
- throw new IgniteSpiException("Failed to execute statement: " + sql, e);
- }
- finally {
- U.close(stmt, log);
- }
- }
-
- /**
- * Removes entry with specified key from any tables (if exist).
- *
- * @param spaceName Space name.
- * @param k Key entity.
- * @param tblToUpdate Table to update.
- * @throws org.apache.ignite.spi.IgniteSpiException In case of error.
- */
- private <K> void removeKey(@Nullable String spaceName, IndexingEntity<K> k, TableDescriptor tblToUpdate)
- throws IgniteSpiException {
- K key = k.value();
-
- try {
- Collection<TableDescriptor> tbls = tables(schema(spaceName));
-
- if (tbls.size() > 1) {
- boolean fixedTyping = isIndexFixedTyping(spaceName);
-
- for (TableDescriptor tbl : tbls) {
- if (tbl != tblToUpdate && (tbl.type().keyClass().equals(key.getClass()) ||
- !fixedTyping)) {
- if (tbl.tbl.update(key, null, 0)) {
- if (tbl.luceneIdx != null)
- tbl.luceneIdx.remove(k);
-
- return;
- }
- }
- }
- }
- }
- catch (Exception e) {
- throw new IgniteSpiException("Failed to remove key: " + key, e);
- }
- }
-
- /**
- * Binds object to prepared statement.
- *
- * @param stmt SQL statement.
- * @param idx Index.
- * @param obj Value to store.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private void bindObject(PreparedStatement stmt, int idx, @Nullable Object obj) throws IgniteSpiException {
- try {
- if (obj == null)
- stmt.setNull(idx, Types.VARCHAR);
- else
- stmt.setObject(idx, obj);
- }
- catch (SQLException e) {
- throw new IgniteSpiException("Failed to bind parameter [idx=" + idx + ", obj=" + obj + ']', e);
- }
- }
-
- /**
- * Handles SQL exception.
- */
- private void onSqlException() {
- Connection conn = connCache.get().connection();
-
- connCache.set(null);
-
- if (conn != null) {
- conns.remove(conn);
-
- // Reset connection to receive new one at next call.
- U.close(conn, log);
- }
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> void store(@Nullable String spaceName, IndexingTypeDescriptor type,
- IndexingEntity<K> k, IndexingEntity<V> v, byte[] ver, long expirationTime)
- throws IgniteSpiException {
- TableDescriptor tbl = tableDescriptor(spaceName, type);
-
- if (tbl == null)
- return; // Type was rejected.
-
- localSpi.set(this);
-
- try {
- removeKey(spaceName, k, tbl);
-
- if (expirationTime == 0)
- expirationTime = Long.MAX_VALUE;
-
- tbl.tbl.update(k.value(), v.value(), expirationTime);
-
- if (tbl.luceneIdx != null)
- tbl.luceneIdx.store(k, v, ver, expirationTime);
- }
- finally {
- localSpi.remove();
- }
- }
-
- /** {@inheritDoc} */
- @Override public <K> boolean remove(@Nullable String spaceName, IndexingEntity<K> k) throws IgniteSpiException {
- assert k != null;
-
- K key = k.value();
-
- if (log.isDebugEnabled())
- log.debug("Removing key from cache query index [locId=" + nodeId + ", key=" + key + ']');
-
- localSpi.set(this);
-
- try {
- for (TableDescriptor tbl : tables(schema(spaceName))) {
- if (tbl.type().keyClass().equals(key.getClass()) || !isIndexFixedTyping(spaceName)) {
- if (tbl.tbl.update(key, null, 0)) {
- if (tbl.luceneIdx != null)
- tbl.luceneIdx.remove(k);
-
- return true;
- }
- }
- }
- }
- finally {
- localSpi.remove();
- }
-
- return false;
- }
-
- /** {@inheritDoc} */
- @Override protected void onContextInitialized0(IgniteSpiContext spiCtx) throws IgniteSpiException {
- ctxInitLatch.countDown();
-
- if (log.isDebugEnabled())
- log.debug("Context has been initialized.");
- }
-
- /** {@inheritDoc} */
- @Override public IgniteSpiContext getSpiContext() {
- if (ctxInitLatch.getCount() != 0) {
- try {
- U.await(ctxInitLatch);
- }
- catch (GridInterruptedException ignored) {
- U.warn(log, "Thread has been interrupted while waiting for SPI context initialization.");
- }
- }
-
- return super.getSpiContext();
- }
-
- /** {@inheritDoc} */
- @Override public <K> void onSwap(@Nullable String spaceName, String swapSpaceName, K key) throws IgniteSpiException {
- Schema schema = schemas.get(schema(spaceName));
-
- if (schema == null)
- return;
-
- localSpi.set(this);
-
- try {
- for (TableDescriptor tbl : schema.values()) {
- if (tbl.type().keyClass().equals(key.getClass()) || !isIndexFixedTyping(spaceName)) {
- try {
- if (tbl.tbl.onSwap(key))
- return;
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
- }
- }
- }
- finally {
- localSpi.remove();
- }
- }
-
- /** {@inheritDoc} */
- @Override public <K, V> void onUnswap(@Nullable String spaceName, K key, V val, byte[] valBytes)
- throws IgniteSpiException {
- localSpi.set(this);
-
- try {
- for (TableDescriptor tbl : tables(schema(spaceName))) {
- if (tbl.type().keyClass().equals(key.getClass()) || !isIndexFixedTyping(spaceName)) {
- try {
- if (tbl.tbl.onUnswap(key, val))
- return;
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
- }
- }
- }
- finally {
- localSpi.remove();
- }
- }
-
- /**
- * Drops table form h2 database and clear all related indexes (h2 text, lucene).
- *
- * @param tbl Table to unregister.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed to unregister.
- */
- private void removeTable(TableDescriptor tbl) throws IgniteSpiException {
- assert tbl != null;
-
- if (log.isDebugEnabled())
- log.debug("Removing query index table: " + tbl.fullTableName());
-
- Connection c = connectionForThread(null);
-
- Statement stmt = null;
-
- try {
- // NOTE: there is no method dropIndex() for lucene engine correctly working.
- // So we have to drop all lucene index.
- // FullTextLucene.dropAll(c); TODO: GG-4015: fix this
-
- stmt = c.createStatement();
-
- String sql = "DROP TABLE IF EXISTS " + tbl.fullTableName();
-
- if (log.isDebugEnabled())
- log.debug("Dropping database index table with SQL: " + sql);
-
- stmt.executeUpdate(sql);
- }
- catch (SQLException e) {
- onSqlException();
-
- throw new IgniteSpiException("Failed to drop database index table [type=" + tbl.type().name() +
- ", table=" + tbl.fullTableName() + "]", e);
- }
- finally {
- U.close(stmt, log);
- }
-
- tbl.tbl.close();
-
- if (tbl.luceneIdx != null)
- U.closeQuiet(tbl.luceneIdx);
-
- ConcurrentMap<String, TableDescriptor> tbls = schemas.get(tbl.schema());
-
- if (!F.isEmpty(tbls))
- tbls.remove(tbl.name());
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked")
- @Override public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> queryText(
- @Nullable String spaceName, String qry, IndexingTypeDescriptor type,
- IndexingQueryFilter filters) throws IgniteSpiException {
- TableDescriptor tbl = tableDescriptor(spaceName, type);
-
- if (tbl != null && tbl.luceneIdx != null)
- return tbl.luceneIdx.query(qry, filters);
-
- return new GridEmptyCloseableIterator<>();
- }
-
- /** {@inheritDoc} */
- @Override public void unregisterType(@Nullable String spaceName, IndexingTypeDescriptor type)
- throws IgniteSpiException {
- TableDescriptor tbl = tableDescriptor(spaceName, type);
-
- if (tbl != null)
- removeTable(tbl);
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked")
- @Override public <K, V> IndexingFieldsResult queryFields(@Nullable final String spaceName, final String qry,
- @Nullable final Collection<Object> params, final IndexingQueryFilter filters)
- throws IgniteSpiException {
- localSpi.set(this);
-
- setFilters(filters);
-
- try {
- Connection conn = connectionForThread(schema(spaceName));
-
- ResultSet rs = executeSqlQueryWithTimer(conn, qry, params);
-
- List<IndexingFieldMetadata> meta = null;
-
- if (rs != null) {
- try {
- ResultSetMetaData rsMeta = rs.getMetaData();
-
- meta = new ArrayList<>(rsMeta.getColumnCount());
-
- for (int i = 1; i <= rsMeta.getColumnCount(); i++) {
- String schemaName = rsMeta.getSchemaName(i);
- String typeName = rsMeta.getTableName(i);
- String name = rsMeta.getColumnLabel(i);
- String type = rsMeta.getColumnClassName(i);
-
- meta.add(new SqlFieldMetadata(schemaName, typeName, name, type));
- }
- }
- catch (SQLException e) {
- throw new IgniteSpiException("Failed to get meta data.", e);
- }
- }
-
- return new IndexingFieldsResultAdapter(meta, new FieldsIterator(rs));
- }
- finally {
- setFilters(null);
-
- localSpi.remove();
- }
- }
-
- /**
- * @param stmt Prepared statement.
- * @return Command type.
- */
- private static int commandType(PreparedStatement stmt) {
- try {
- return ((CommandInterface)COMMAND_FIELD.get(stmt)).getCommandType();
- }
- catch (IllegalAccessException e) {
- throw new IllegalStateException(e);
- }
- }
-
- /**
- * Executes sql query.
- *
- * @param conn Connection,.
- * @param sql Sql query.
- * @param params Parameters.
- * @return Result.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- @Nullable private ResultSet executeSqlQuery(Connection conn, String sql,
- @Nullable Collection<Object> params) throws IgniteSpiException {
- PreparedStatement stmt;
-
- try {
- stmt = conn.prepareStatement(sql);
- }
- catch (SQLException e) {
- if (e.getErrorCode() == ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1)
- return null;
-
- throw new IgniteSpiException("Failed to parse SQL query: " + sql, e);
- }
-
- switch (commandType(stmt)) {
- case CommandInterface.SELECT:
- case CommandInterface.CALL:
- case CommandInterface.EXPLAIN:
- case CommandInterface.ANALYZE:
- break;
- default:
- throw new IgniteSpiException("Failed to execute non-query SQL statement: " + sql);
- }
-
- bindParameters(stmt, params);
-
- try {
- return stmt.executeQuery();
- }
- catch (SQLException e) {
- throw new IgniteSpiException("Failed to execute SQL query.", e);
- }
- }
-
- /**
- * Executes sql query and prints warning if query is too slow..
- *
- * @param conn Connection,.
- * @param sql Sql query.
- * @param params Parameters.
- * @return Result.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private ResultSet executeSqlQueryWithTimer(Connection conn, String sql,
- @Nullable Collection<Object> params) throws IgniteSpiException {
- long start = U.currentTimeMillis();
-
- try {
- ResultSet rs = executeSqlQuery(conn, sql, params);
-
- long time = U.currentTimeMillis() - start;
-
- if (time > longQryExecTimeout) {
- String msg = "Query execution is too long (" + time + " ms): " + sql;
-
- String longMsg = msg;
-
- if (longQryExplain) {
- ResultSet plan = executeSqlQuery(conn, "EXPLAIN " + sql, params);
-
- if (plan == null)
- longMsg = "Failed to explain plan because required table does not exist: " + sql;
- else {
- plan.next();
-
- // Add SQL explain result message into log.
- longMsg = "Query execution is too long [time=" + time + " ms, sql='" + sql + '\'' +
- ", plan=" + U.nl() + plan.getString(1) + U.nl() + ", parameters=" + params + "]";
- }
- }
-
- LT.warn(log, null, longMsg, msg);
- }
-
- return rs;
- }
- catch (SQLException e) {
- onSqlException();
-
- throw new IgniteSpiException(e);
- }
- }
-
- /**
- * Executes query.
- *
- * @param qry Query.
- * @param params Query parameters.
- * @param tbl Target table of query to generate select.
- * @return Result set.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private ResultSet executeQuery(String qry, @Nullable Collection<Object> params,
- @Nullable TableDescriptor tbl) throws IgniteSpiException {
- Connection conn = connectionForThread(tbl != null ? tbl.schema() : "PUBLIC");
-
- String sql = generateQuery(qry, tbl);
-
- return executeSqlQueryWithTimer(conn, sql, params);
- }
-
- /**
- * Binds parameters to prepared statement.
- *
- * @param stmt Prepared statement.
- * @param params Parameters collection.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private void bindParameters(PreparedStatement stmt, @Nullable Collection<Object> params) throws IgniteSpiException {
- if (!F.isEmpty(params)) {
- int idx = 1;
-
- for (Object arg : params)
- bindObject(stmt, idx++, arg);
- }
- }
-
- /**
- * Executes regular query.
- * Note that SQL query can not refer to table alias, so use full table name instead.
- *
- * @param spaceName Space name.
- * @param qry Query.
- * @param params Query parameters.
- * @param type Query return type.
- * @param filters Space name and key filters.
- * @return Queried rows.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- @SuppressWarnings("unchecked")
- @Override public <K, V> IgniteSpiCloseableIterator<IndexingKeyValueRow<K, V>> query(@Nullable String spaceName,
- final String qry, @Nullable final Collection<Object> params, IndexingTypeDescriptor type,
- final IndexingQueryFilter filters) throws IgniteSpiException {
- final TableDescriptor tbl = tableDescriptor(spaceName, type);
-
- if (tbl == null)
- return new GridEmptyCloseableIterator<>();
-
- setFilters(filters);
-
- localSpi.set(this);
-
- try {
- ResultSet rs = executeQuery(qry, params, tbl);
-
- return new KeyValIterator(rs);
- }
- finally {
- setFilters(null);
-
- localSpi.remove();
- }
- }
-
- /**
- * Sets filters for current thread. Must be set to not null value
- * before executeQuery and reset to null after in finally block since it signals
- * to table that it should return content without expired values.
- *
- * @param filters Filters.
- */
- private void setFilters(@Nullable IndexingQueryFilter filters) {
- GridH2IndexBase.setFiltersForThread(filters);
- }
-
- /**
- * Prepares statement for query.
- *
- * @param qry Query string.
- * @param tbl Table to use.
- * @return Prepared statement.
- * @throws org.apache.ignite.spi.IgniteSpiException In case of error.
- */
- private String generateQuery(String qry, @Nullable TableDescriptor tbl) throws IgniteSpiException {
- boolean needSelect = tbl != null;
-
- String str = qry.trim().toUpperCase();
-
- if (!str.startsWith("FROM")) {
- if (str.startsWith("SELECT")) {
- if (needSelect) {
- StringTokenizer st = new StringTokenizer(str, " ");
-
- String errMsg = "Wrong query format, query must start with 'select * from' " +
- "or 'from' or without such keywords.";
-
- if (st.countTokens() > 3) {
- st.nextToken();
- String wildcard = st.nextToken();
- String from = st.nextToken();
-
- if (!"*".equals(wildcard) || !"FROM".equals(from))
- throw new IgniteSpiException(errMsg);
-
- needSelect = false;
- }
- else
- throw new IgniteSpiException(errMsg);
- }
- }
- else {
- boolean needWhere = !str.startsWith("ORDER") && !str.startsWith("LIMIT");
-
- qry = needWhere ? "FROM " + tbl.fullTableName() + " WHERE " + qry :
- "FROM " + tbl.fullTableName() + ' ' + qry;
- }
- }
-
- GridStringBuilder ptrn = new SB("SELECT {0}.").a(KEY_FIELD_NAME);
-
- ptrn.a(", {0}.").a(VAL_FIELD_NAME);
-
- return needSelect ? MessageFormat.format(ptrn.toString(), tbl.fullTableName()) + ' ' + qry : qry;
- }
-
- /**
- * Registers new class description.
- *
- * This implementation doesn't support type reregistration.
- *
- * @param type Type description.
- * @throws org.apache.ignite.spi.IgniteSpiException In case of error.
- */
- @Override public boolean registerType(@Nullable String spaceName, IndexingTypeDescriptor type)
- throws IgniteSpiException {
- if (!validateTypeDescriptor(spaceName, type))
- return false;
-
- for (TableDescriptor table : tables(schema(spaceName)))
- // Need to compare class names rather than classes to define
- // whether a class was previously undeployed.
- if (table.type().valueClass().getClass().getName().equals(type.valueClass().getName()))
- throw new IgniteSpiException("Failed to register type in query index because" +
- " class is already registered (most likely that class with the same name" +
- " was not properly undeployed): " + type);
-
- TableDescriptor tbl = new TableDescriptor(spaceName, type);
-
- try {
- Connection conn = connectionForThread(null);
-
- Schema schema = schemas.get(tbl.schema());
-
- if (schema == null) {
- schema = new Schema(spaceName);
-
- Schema existing = schemas.putIfAbsent(tbl.schema(), schema);
-
- if (existing != null)
- schema = existing;
- }
-
- createTable(schema, tbl, conn);
-
- schema.put(tbl.name(), tbl);
- }
- catch (SQLException e) {
- onSqlException();
-
- throw new IgniteSpiException("Failed to register query type: " + type, e);
- }
-
- return true;
- }
-
- /**
- * @param cls Class.
- * @return True if given class has primitive respective sql type.
- */
- private boolean isPrimitive(Class<?> cls) {
- DBTypeEnum valType = DBTypeEnum.fromClass(cls);
-
- return valType != DBTypeEnum.BINARY && valType != DBTypeEnum.OTHER &&
- valType != DBTypeEnum.ARRAY;
- }
-
- /**
- * Validates properties described by query types.
- *
- * @param spaceName Space name.
- * @param type Type descriptor.
- * @return True if type is valid.
- * @throws org.apache.ignite.spi.IgniteSpiException If validation failed.
- */
- private boolean validateTypeDescriptor(@Nullable String spaceName, IndexingTypeDescriptor type)
- throws IgniteSpiException {
- assert type != null;
-
- boolean keyPrimitive = isPrimitive(type.keyClass());
- boolean valPrimitive = isPrimitive(type.valueClass());
-
- // Do not register if value is not primitive and
- // there are no indexes or fields defined.
- if (!type.valueTextIndex() && type.indexes().isEmpty() &&
- type.keyFields().isEmpty() && type.valueFields().isEmpty())
- return keyPrimitive && isIndexPrimitiveKey(spaceName) || valPrimitive && isIndexPrimitiveValue(spaceName);
-
- Collection<String> names = new HashSet<>();
-
- names.addAll(type.keyFields().keySet());
- names.addAll(type.valueFields().keySet());
-
- if (names.size() < type.keyFields().size() + type.valueFields().size())
- throw new IgniteSpiException("Found duplicated properties with the same name [keyType=" +
- type.keyClass().getName() + ", valueType=" + type.valueClass().getName() + "]");
-
- String ptrn = "Name ''{0}'' is reserved and cannot be used as a field name [class=" + type + "]";
-
- for (String name : names) {
- if (name.equals(KEY_FIELD_NAME) || name.equals(VAL_FIELD_NAME))
- throw new IgniteSpiException(MessageFormat.format(ptrn, name));
- }
-
- return true;
- }
-
- /**
- * Escapes name to be valid SQL identifier. Currently just replaces '.' and '$' sign with '_'.
- *
- * @param name Name.
- * @param escapeAll Escape flag.
- * @return Escaped name.
- */
- private static String escapeName(String name, boolean escapeAll) {
- if (escapeAll)
- return "\"" + name + "\"";
-
- SB sb = null;
-
- for (int i = 0; i < name.length(); i++) {
- char ch = name.charAt(i);
-
- if (!Character.isLetter(ch) && !Character.isDigit(ch) && ch != '_' &&
- !(ch == '"' && (i == 0 || i == name.length() - 1)) && ch != '-') {
- // Class name can also contain '$' or '.' - these should be escaped.
- assert ch == '$' || ch == '.';
-
- if (sb == null)
- sb = new SB();
-
- sb.a(name.substring(sb.length(), i));
-
- // Replace illegal chars with '_'.
- sb.a('_');
- }
- }
-
- if (sb == null)
- return name;
-
- sb.a(name.substring(sb.length(), name.length()));
-
- return sb.toString();
- }
-
- /**
- * Create db table by using given table descriptor.
- *
- * @param schema Schema.
- * @param tbl Table descriptor.
- * @param conn Connection.
- * @throws SQLException If failed to create db table.
- */
- private void createTable(Schema schema, TableDescriptor tbl, Connection conn) throws SQLException {
- assert tbl != null;
-
- boolean keyAsObj = !isIndexFixedTyping(schema.spaceName);
-
- boolean escapeAll = isEscapeAll(schema.spaceName);
-
- String keyType = keyAsObj ? "OTHER" : dbTypeFromClass(tbl.type().keyClass());
- String valTypeStr = dbTypeFromClass(tbl.type().valueClass());
-
- SB sql = new SB();
-
- sql.a("CREATE TABLE ").a(tbl.fullTableName()).a(" (")
- .a(KEY_FIELD_NAME).a(' ').a(keyType).a(" NOT NULL");
-
- sql.a(',').a(VAL_FIELD_NAME).a(' ').a(valTypeStr);
-
- for (Map.Entry<String, Class<?>> e: tbl.type().keyFields().entrySet())
- sql.a(',').a(escapeName(e.getKey(), escapeAll)).a(' ').a(dbTypeFromClass(e.getValue()));
-
- for (Map.Entry<String, Class<?>> e: tbl.type().valueFields().entrySet())
- sql.a(',').a(escapeName(e.getKey(), escapeAll)).a(' ').a(dbTypeFromClass(e.getValue()));
-
- sql.a(')');
-
- if (log.isDebugEnabled())
- log.debug("Creating DB table with SQL: " + sql);
-
- GridH2RowDescriptor desc = new RowDescriptor(tbl.type(), schema, keyAsObj);
-
- GridH2Table.Engine.createTable(conn, sql.toString(), desc, tbl, tbl.spaceName);
- }
-
- /**
- * Gets corresponding DB type from java class.
- *
- * @param cls Java class.
- * @return DB type name.
- */
- private String dbTypeFromClass(Class<?> cls) {
- return DBTypeEnum.fromClass(cls).dBTypeAsString();
- }
-
- /**
- * Gets table descriptor by value type.
- *
- * @param spaceName Space name.
- * @param type Value type descriptor.
- * @return Table descriptor or {@code null} if not found.
- */
- @Nullable private TableDescriptor tableDescriptor(@Nullable String spaceName, IndexingTypeDescriptor type) {
- return tableDescriptor(type.name(), spaceName);
- }
-
- /**
- * Gets table descriptor by type and space names.
- *
- * @param type Type name.
- * @param space Space name.
- * @return Table descriptor.
- */
- @Nullable private TableDescriptor tableDescriptor(String type, @Nullable String space) {
- ConcurrentMap<String, TableDescriptor> tbls = schemas.get(schema(space));
-
- if (tbls == null)
- return null;
-
- return tbls.get(type);
- }
-
- /**
- * Gets collection of table for given schema name.
- *
- * @param schema Schema name.
- * @return Collection of table descriptors.
- */
- private Collection<TableDescriptor> tables(String schema) {
- ConcurrentMap<String, TableDescriptor> tbls = schemas.get(schema);
-
- if (tbls == null)
- return Collections.emptySet();
-
- return tbls.values();
- }
-
- /**
- * Gets database schema from space.
- *
- * @param space Space name.
- * @return Schema name.
- */
- private static String schema(@Nullable String space) {
- if (F.isEmpty(space))
- return "PUBLIC";
-
- return space;
- }
-
- /** {@inheritDoc} */
- @Override public void rebuildIndexes(@Nullable String spaceName, IndexingTypeDescriptor type) {
- if (offheap != null)
- throw new UnsupportedOperationException("Index rebuilding is not supported when off-heap memory is used");
-
- TableDescriptor tbl = tableDescriptor(spaceName, type);
-
- if (tbl == null)
- return;
-
- tbl.tbl.rebuildIndexes();
- }
-
- /** {@inheritDoc} */
- @Override public long size(@Nullable String spaceName, IndexingTypeDescriptor type) throws IgniteSpiException {
- TableDescriptor tbl = tableDescriptor(spaceName, type);
-
- if (tbl == null)
- return -1;
-
- IgniteSpiCloseableIterator<List<IndexingEntity<?>>> iter = queryFields(spaceName,
- "SELECT COUNT(*) FROM " + tbl.fullTableName(), null, null).iterator();
-
- if (!iter.hasNext())
- throw new IllegalStateException();
-
- return ((IndexingEntityAdapter<Number>)iter.next().get(0)).value().longValue();
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("NonThreadSafeLazyInitialization")
- @Override public void spiStart(@Nullable String gridName) throws IgniteSpiException {
- if (log.isDebugEnabled())
- log.debug("Starting cache query index...");
-
- assertParameter(idxWriteLockWaitTime > 0, "'idxWriteLockWaitTime' must be positive.");
-
- startStopwatch();
-
- System.setProperty("h2.serializeJavaObject", "false");
-
- if (SysProperties.serializeJavaObject) {
- U.warn(log, "Serialization of Java objects in H2 was enabled.");
-
- SysProperties.serializeJavaObject = false;
- }
-
- if (useOptimizedSerializer)
- Utils.serializer = h2Serializer();
-
- if (maxOffHeapMemory != -1) {
- assert maxOffHeapMemory >= 0 : maxOffHeapMemory;
-
- offheap = new GridUnsafeMemory(maxOffHeapMemory);
- }
-
- SB opt = new SB();
-
- opt.a(DFLT_DB_OPTIONS).a(OPTIMIZED_DB_OPTIONS);
-
- String dbName = UUID.randomUUID() + "_" + gridName + "_" + getName();
-
- dbUrl = "jdbc:h2:mem:" + DFLT_DB_NAME + "_" + dbName + opt;
-
- try {
- Class.forName("org.h2.Driver");
- }
- catch (ClassNotFoundException e) {
- throw new IgniteSpiException("Failed to find org.h2.Driver class", e);
- }
-
- for (String schema : schemaNames)
- createSchemaIfAbsent(schema);
-
- try {
- createSqlFunctions();
- runInitScript();
-
- if (getString(GG_H2_DEBUG_CONSOLE) != null) {
- Connection c = DriverManager.getConnection(dbUrl);
-
- WebServer webSrv = new WebServer();
- Server web = new Server(webSrv, "-webPort", "0");
- web.start();
- String url = webSrv.addSession(c);
-
- try {
- Server.openBrowser(url);
- }
- catch (Exception e) {
- U.warn(log, "Failed to open browser: " + e.getMessage());
- }
- }
- }
- catch (SQLException e) {
- throw new IgniteSpiException(e);
- }
-
- registerMBean(gridName, this, GridH2IndexingSpiMBean.class);
-
- if (log.isDebugEnabled())
- log.debug("Cache query index started [grid=" + gridName + ", cache=" + getName() + "]");
- }
-
- /**
- * @return Serializer.
- */
- protected JavaObjectSerializer h2Serializer() {
- return new H2Serializer();
- }
-
- /**
- * Runs initial script.
- *
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- * @throws SQLException If failed.
- */
- private void runInitScript() throws IgniteSpiException, SQLException {
- if (initScriptPath == null)
- return;
-
- try (PreparedStatement p = connectionForThread(null).prepareStatement("RUNSCRIPT FROM ? CHARSET 'UTF-8'")) {
- p.setString(1, initScriptPath);
-
- p.execute();
- }
- }
-
- /**
- * Registers SQL functions.
- *
- * @throws SQLException If failed.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- private void createSqlFunctions() throws SQLException, IgniteSpiException {
- if (F.isEmpty(idxCustomFuncClss))
- return;
-
- for (Class<?> cls : idxCustomFuncClss) {
- for (Method m : cls.getDeclaredMethods()) {
- GridCacheQuerySqlFunction ann = m.getAnnotation(GridCacheQuerySqlFunction.class);
-
- if (ann != null) {
- int modifiers = m.getModifiers();
-
- if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers))
- throw new IgniteSpiException("Method " + m.getName() + " must be public static.");
-
- String alias = ann.alias().isEmpty() ? m.getName() : ann.alias();
-
- String clause = "CREATE ALIAS " + alias + (ann.deterministic() ? " DETERMINISTIC FOR \"" :
- " FOR \"") + cls.getName() + '.' + m.getName() + '"';
-
- Collection<String> schemas = new ArrayList<>(schemaNames);
-
- if (!schemaNames.contains(schema(null)))
- schemas.add(schema(null));
-
- for (String schema : schemas) {
- Connection c = connectionForThread(schema);
-
- Statement s = c.createStatement();
-
- s.execute(clause);
-
- s.close();
- }
- }
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override public void spiStop() throws IgniteSpiException {
- if (log.isDebugEnabled())
- log.debug("Stopping cache query index...");
-
- if (ctxInitLatch.getCount() != 0)
- ctxInitLatch.countDown();
-
- unregisterMBean();
-
- Connection conn = connectionForThread(null);
-
- for (ConcurrentMap<String, TableDescriptor> m : schemas.values()) {
- for (TableDescriptor desc : m.values()) {
- desc.tbl.close();
-
- if (desc.luceneIdx != null)
- U.closeQuiet(desc.luceneIdx);
- }
- }
-
- if (conn != null) {
- Statement stmt = null;
-
- try {
- stmt = conn.createStatement();
-
- stmt.execute("DROP ALL OBJECTS DELETE FILES");
- stmt.execute("SHUTDOWN");
- }
- catch (SQLException e) {
- throw new IgniteSpiException("Failed to shutdown database.", e);
- }
- finally {
- U.close(stmt, log);
- }
- }
-
- for (Connection c : conns)
- U.close(c, log);
-
- conns.clear();
- schemas.clear();
- rowCache.clear();
-
- if (log.isDebugEnabled())
- log.debug("Cache query index stopped [cache=" + getName() + "]");
- }
-
- /**
- * Sets classes with methods annotated by {@link GridCacheQuerySqlFunction}
- * to be used as user-defined functions from SQL queries.
- *
- * @param idxCustomFuncClss List of classes.
- */
- public void setIndexCustomFunctionClasses(Class<?>... idxCustomFuncClss) {
- this.idxCustomFuncClss = idxCustomFuncClss;
- }
-
- /** {@inheritDoc} */
- @Override public String getSpaceNames() {
- return StringUtils.arrayCombine(spaceCfgs.keySet().toArray(new String[spaceCfgs.size()]), ',');
- }
-
- /**
- * The flag indicating that {@link JavaObjectSerializer} for H2 database will be set to optimized version.
- * This setting usually makes sense for offheap indexing only.
- * <p>
- * Default is {@link #DFLT_USE_OPTIMIZED_SERIALIZER}.
- *
- * @param useOptimizedSerializer Flag value.
- */
- public void setUseOptimizedSerializer(boolean useOptimizedSerializer) {
- this.useOptimizedSerializer = useOptimizedSerializer;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isUseOptimizedSerializer() {
- return useOptimizedSerializer;
- }
-
- /** {@inheritDoc} */
- @Override public long getLongQueryExecutionTimeout() {
- return longQryExecTimeout;
- }
-
- /**
- * Set query execution time threshold. If queries exceed this threshold,
- * then a warning will be printed out. If {@link #setLongQueryExplain(boolean)} is
- * set to {@code true}, then execution plan will be printed out as well.
- * <p>
- * If not provided, default value is defined by {@link #DFLT_LONG_QRY_EXEC_TIMEOUT}.
- *
- * @param longQryExecTimeout Long query execution timeout.
- * @see #setLongQueryExplain(boolean)
- */
- @IgniteSpiConfiguration(optional = true)
- public void setLongQueryExecutionTimeout(long longQryExecTimeout) {
- this.longQryExecTimeout = longQryExecTimeout;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isLongQueryExplain() {
- return longQryExplain;
- }
-
- /**
- * If {@code true}, SPI will print SQL execution plan for long queries (explain SQL query).
- * The time threshold of long queries is controlled via {@link #setLongQueryExecutionTimeout(long)}
- * parameter.
- * <p>
- * If not provided, default value is {@code false}.
- *
- * @param longQryExplain Flag marking SPI should print SQL execution plan for long queries (explain SQL query).
- * @see #setLongQueryExecutionTimeout(long)
- */
- @IgniteSpiConfiguration(optional = true)
- public void setLongQueryExplain(boolean longQryExplain) {
- this.longQryExplain = longQryExplain;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isIndexPrimitiveKey(@Nullable String spaceName) {
- GridH2IndexingSpaceConfiguration cfg = spaceCfgs.get(spaceName);
-
- if (cfg != null)
- return cfg.isIndexPrimitiveKey();
-
- return dfltIdxPrimitiveKey;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isIndexPrimitiveValue(String spaceName) {
- GridH2IndexingSpaceConfiguration cfg = spaceCfgs.get(spaceName);
-
- if (cfg != null)
- return cfg.isIndexPrimitiveValue();
-
- return dfltIdxPrimitiveVal;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isIndexFixedTyping(String spaceName) {
- GridH2IndexingSpaceConfiguration cfg = spaceCfgs.get(spaceName);
-
- if (cfg != null)
- return cfg.isIndexFixedTyping();
-
- return dfltIdxFixedTyping;
- }
-
- /**
- * Sets if SPI will index primitive key-value pairs by value. Makes sense only if
- * {@link #setDefaultIndexPrimitiveKey(boolean)} set to true.
- *
- * @param dfltIdxPrimitiveVal Flag value.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setDefaultIndexPrimitiveValue(boolean dfltIdxPrimitiveVal) {
- this.dfltIdxPrimitiveVal = dfltIdxPrimitiveVal;
- }
-
- /**
- * Gets if SPI will index primitive key-value pairs by value. Makes sense only if
- * {@link #setDefaultIndexPrimitiveKey(boolean)} set to true.
- *
- * @return Flag value.
- */
- @Override public boolean isDefaultIndexPrimitiveValue() {
- return dfltIdxPrimitiveVal;
- }
-
- /**
- * Sets if SPI will index primitive key-value pairs by key.
- *
- * @param dfltIdxPrimitiveKey Flag value.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setDefaultIndexPrimitiveKey(boolean dfltIdxPrimitiveKey) {
- this.dfltIdxPrimitiveKey = dfltIdxPrimitiveKey;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isDefaultIndexPrimitiveKey() {
- return dfltIdxPrimitiveKey;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isDefaultIndexFixedTyping() {
- return dfltIdxFixedTyping;
- }
-
- /**
- * This flag essentially controls whether all values of the same type have
- * identical key type.
- * <p>
- * If {@code false}, SPI will store all keys in BINARY form to make it possible to store
- * the same value type with different key types. If {@code true}, key type will be converted
- * to respective SQL type if it is possible, hence, improving performance of queries.
- * <p>
- * Setting this value to {@code false} also means that {@code '_key'} column cannot be indexed and
- * cannot participate in query where clauses. The behavior of using '_key' column in where
- * clauses with this flag set to {@code false} is undefined.
- * <p>
- * This property can be overridden on per-space level via {@link GridH2IndexingSpaceConfiguration}.
- *
- * @param dfltIdxFixedTyping FLag value.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setDefaultIndexFixedTyping(boolean dfltIdxFixedTyping) {
- this.dfltIdxFixedTyping = dfltIdxFixedTyping;
- }
-
- /**
- * Sets maximum amount of memory available to off-heap storage. Possible values are
- * <ul>
- * <li>{@code -1} - Means that off-heap storage is disabled.</li>
- * <li>
- * {@code 0} - GridGain will not limit off-heap storage (it's up to user to properly
- * add and remove entries from cache to ensure that off-heap storage does not grow
- * indefinitely.
- * </li>
- * <li>Any positive value specifies the limit of off-heap storage in bytes.</li>
- * </ul>
- * Default value is {@code -1}, which means that off-heap storage is disabled by default.
- * <p>
- * Use off-heap storage to load gigabytes of data in memory without slowing down
- * Garbage Collection. Essentially in this case you should allocate very small amount
- * of memory to JVM and GridGain will cache most of the data in off-heap space
- * without affecting JVM performance at all.
- *
- * @param maxOffHeapMemory Maximum memory in bytes available to off-heap memory space.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setMaxOffHeapMemory(long maxOffHeapMemory) {
- this.maxOffHeapMemory = maxOffHeapMemory;
- }
-
- /** {@inheritDoc} */
- @Override public long getMaxOffHeapMemory() {
- return maxOffHeapMemory;
- }
-
- /**
- * Sets index write lock wait time in milliseconds. This parameter can affect query performance under high
- * thread contention. Default value is {@code 100}.
- *
- * @param idxWriteLockWaitTime Index write lock wait time.
- */
- public void setIndexWriteLockWaitTime(long idxWriteLockWaitTime) {
- this.idxWriteLockWaitTime = idxWriteLockWaitTime;
- }
-
- /** {@inheritDoc} */
- @Override public long getIndexWriteLockWaitTime() {
- return idxWriteLockWaitTime;
- }
-
- /**
- * Specifies max allowed size of cache for deserialized offheap rows to avoid deserialization costs for most
- * frequently used ones. In general performance is better with greater cache size. Must be more than 128 items.
- *
- * @param size Cache size in items.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setMaxOffheapRowsCacheSize(int size) {
- A.ensure(size >= 128, "Offheap rows cache size must be not less than 128.");
-
- rowCache = new CacheLongKeyLIRS<>(size, 1, 128, 256);
- }
-
- /**
- * Sets the optional search path consisting of space names to search SQL schema objects. Useful for cross cache
- * queries to avoid writing fully qualified table names.
- *
- * @param searchPath Search path.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setSearchPath(String... searchPath) {
- this.searchPath = searchPath;
- }
-
- /** {@inheritDoc} */
- @Nullable @Override public String[] getSearchPath() {
- return searchPath;
- }
-
- /** {@inheritDoc} */
- @Nullable @Override public String getInitialScriptPath() {
- return initScriptPath;
- }
-
- /**
- * Sets script path to be ran against H2 database after opening.
- * The script must be UTF-8 encoded file.
- *
- * @param initScriptPath Script path.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setInitialScriptPath(String initScriptPath) {
- this.initScriptPath = initScriptPath;
- }
-
- /**
- * This flag controls generation of 'create table' SQL.
- * <p>
- * If {@code true}, then table name and all column names in 'create table' SQL
- * generated by SPI are escaped with double quotes. This flag should be set if table name of
- * column name is H2 reserved word or is not valid H2 identifier (e.g. contains space or hyphen).
- * <p>
- * Note if this flag is set then table and column name in SQL queries also must be escaped with double quotes.
- * <p>
- * This property can be overridden on per-space level via {@link GridH2IndexingSpaceConfiguration}.
- *
- * @param dfltEscapeAll Default flag value.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setDefaultEscapeAll(boolean dfltEscapeAll) {
- this.dfltEscapeAll = dfltEscapeAll;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isDefaultEscapeAll() {
- return dfltEscapeAll;
- }
-
- /** {@inheritDoc} */
- @Override public boolean isEscapeAll(String spaceName) {
- GridH2IndexingSpaceConfiguration cfg = spaceCfgs.get(spaceName);
-
- if (cfg != null)
- return cfg.isEscapeAll();
-
- return dfltEscapeAll;
- }
-
- /** {@inheritDoc} */
- @Override public int getMaxOffheapRowsCacheSize() {
- return (int)rowCache.getMaxMemory();
- }
-
- /** {@inheritDoc} */
- @Override public int getOffheapRowsCacheSize() {
- return (int)rowCache.getUsedMemory();
- }
-
- /** {@inheritDoc} */
- @Override public long getAllocatedOffHeapMemory() {
- return offheap == null ? -1 : offheap.allocatedSize();
- }
-
- /** {@inheritDoc} */
- @Override public void registerMarshaller(IndexingMarshaller marshaller) {
- this.marshaller = marshaller;
- }
-
- /** {@inheritDoc} */
- @Override public void registerSpace(String spaceName) throws IgniteSpiException {
- schemaNames.add(schema(spaceName));
-
- if (!spaceCfgs.containsKey(spaceName))
- spaceCfgs.put(spaceName, null);
- }
-
- /**
- * Sets per-space configurations.
- *
- * @param spaceCfgs Space configurations list.
- */
- @IgniteSpiConfiguration(optional = true)
- public void setSpaceConfigurations(GridH2IndexingSpaceConfiguration... spaceCfgs) {
- Map<String , GridH2IndexingSpaceConfiguration> map = new HashMap<>();
-
- for (GridH2IndexingSpaceConfiguration cfg : spaceCfgs) {
- GridH2IndexingSpaceConfiguration old = map.put(cfg.getName(), cfg);
-
- if (old != null)
- throw new IllegalArgumentException("Space configured twice: " + cfg.getName());
- }
-
- this.spaceCfgs = map;
- }
-
- /**
- * Wrapper to store connection and flag is schema set or not.
- */
- private static class ConnectionWrapper {
- /** */
- private Connection conn;
-
- /** */
- private volatile String schema;
-
- /**
- * @param conn Connection to use.
- */
- ConnectionWrapper(Connection conn) {
- this.conn = conn;
- }
-
- /**
- * @return Schema name if schema is set, null otherwise.
- */
- public String schema() {
- return schema;
- }
-
- /**
- * @param schema Schema name set on this connection.
- */
- public void schema(@Nullable String schema) {
- this.schema = schema;
- }
-
- /**
- * @return Connection.
- */
- public Connection connection() {
- return conn;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(ConnectionWrapper.class, this);
- }
- }
-
- /**
- * Enum that helps to map java types to database types.
- */
- private enum DBTypeEnum {
- /** */
- INT("INT"),
-
- /** */
- BOOL("BOOL"),
-
- /** */
- TINYINT("TINYINT"),
-
- /** */
- SMALLINT("SMALLINT"),
-
- /** */
- BIGINT("BIGINT"),
-
- /** */
- DECIMAL("DECIMAL"),
-
- /** */
- DOUBLE("DOUBLE"),
-
- /** */
- REAL("REAL"),
-
- /** */
- TIME("TIME"),
-
- /** */
- TIMESTAMP("TIMESTAMP"),
-
- /** */
- DATE("DATE"),
-
- /** */
- VARCHAR("VARCHAR"),
-
- /** */
- CHAR("CHAR"),
-
- /** */
- BINARY("BINARY"),
-
- /** */
- UUID("UUID"),
-
- /** */
- ARRAY("ARRAY"),
-
- /** */
- GEOMETRY("GEOMETRY"),
-
- /** */
- OTHER("OTHER");
-
- /** Map of Class to enum. */
- private static final Map<Class<?>, DBTypeEnum> map = new HashMap<>();
-
- /**
- * Initialize map of DB types.
- */
- static {
- map.put(int.class, INT);
- map.put(Integer.class, INT);
- map.put(boolean.class, BOOL);
- map.put(Boolean.class, BOOL);
- map.put(byte.class, TINYINT);
- map.put(Byte.class, TINYINT);
- map.put(short.class, SMALLINT);
- map.put(Short.class, SMALLINT);
- map.put(long.class, BIGINT);
- map.put(Long.class, BIGINT);
- map.put(BigDecimal.class, DECIMAL);
- map.put(double.class, DOUBLE);
- map.put(Double.class, DOUBLE);
- map.put(float.class, REAL);
- map.put(Float.class, REAL);
- map.put(Time.class, TIME);
- map.put(Timestamp.class, TIMESTAMP);
- map.put(java.util.Date.class, TIMESTAMP);
- map.put(java.sql.Date.class, DATE);
- map.put(char.class, CHAR);
- map.put(Character.class, CHAR);
- map.put(String.class, VARCHAR);
- map.put(UUID.class, UUID);
- map.put(byte[].class, BINARY);
- }
-
- /** */
- private final String dbType;
-
- /**
- * Constructs new instance.
- *
- * @param dbType DB type name.
- */
- DBTypeEnum(String dbType) {
- this.dbType = dbType;
- }
-
- /**
- * Resolves enum by class.
- *
- * @param cls Class.
- * @return Enum value.
- */
- public static DBTypeEnum fromClass(Class<?> cls) {
- DBTypeEnum res = map.get(cls);
-
- if (res != null)
- return res;
-
- if (DataType.isGeometryClass(cls))
- return GEOMETRY;
-
- return cls.isArray() && !cls.getComponentType().isPrimitive() ? ARRAY : OTHER;
- }
-
- /**
- * Gets DB type name.
- *
- * @return DB type name.
- */
- public String dBTypeAsString() {
- return dbType;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(DBTypeEnum.class, this);
- }
- }
-
- /**
- * Information about table in database.
- */
- private class TableDescriptor implements GridH2Table.IndexesFactory {
- /** */
- private final String fullTblName;
-
- /** */
- private final IndexingTypeDescriptor type;
-
- /** */
- private final String spaceName;
-
- /** */
- private final String schema;
-
- /** */
- private GridH2Table tbl;
-
- /** */
- private GridLuceneIndex luceneIdx;
-
- /**
- * @param spaceName Space name.
- * @param type Type descriptor.
- */
- TableDescriptor(@Nullable String spaceName, IndexingTypeDescriptor type) {
- this.spaceName = spaceName;
- this.type = type;
-
- schema = GridH2IndexingSpi.schema(spaceName);
-
- fullTblName = '\"' + schema + "\"." + escapeName(type.name(), isEscapeAll(spaceName));
- }
-
- /**
- * @return Schema name.
- */
- public String schema() {
- return schema;
- }
-
- /**
- * @return Database table name.
- */
- String fullTableName() {
- return fullTblName;
- }
-
- /**
- * @return Database table name.
- */
- String name() {
- return type.name();
- }
-
- /**
- * @return Type.
- */
- IndexingTypeDescriptor type() {
- return type;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(TableDescriptor.class, this);
- }
-
- /** {@inheritDoc} */
- @Override public ArrayList<Index> createIndexes(GridH2Table tbl) {
- this.tbl = tbl;
-
- ArrayList<Index> idxs = new ArrayList<>();
-
- idxs.add(new GridH2TreeIndex("_key_PK", tbl, true, KEY_COL, VAL_COL, tbl.indexColumn(0, ASCENDING)));
-
- if (type().valueClass() == String.class) {
- try {
- luceneIdx = new GridLuceneIndex(marshaller, offheap, spaceName, type, true);
- }
- catch (IgniteSpiException e1) {
- throw new GridRuntimeException(e1);
- }
- }
-
- for (Map.Entry<String, IndexDescriptor> e : type.indexes().entrySet()) {
- String name = e.getKey();
- IndexDescriptor idx = e.getValue();
-
- if (idx.type() == FULLTEXT) {
- try {
- luceneIdx = new GridLuceneIndex(marshaller, offheap, spaceName, type, true);
- }
- catch (IgniteSpiException e1) {
- throw new GridRuntimeException(e1);
- }
- }
- else {
- IndexColumn[] cols = new IndexColumn[idx.fields().size()];
-
- int i = 0;
-
- boolean escapeAll = isEscapeAll(spaceName);
-
- for (String field : idx.fields()) {
- // H2 reserved keywords used as column name is case sensitive.
- String fieldName = escapeAll ? field : escapeName(field, escapeAll).toUpperCase();
-
- Column col = tbl.getColumn(fieldName);
-
- cols[i++] = tbl.indexColumn(col.getColumnId(), idx.descending(field) ? DESCENDING : ASCENDING);
- }
-
- if (idx.type() == SORTED)
- idxs.add(new GridH2TreeIndex(name, tbl, false, KEY_COL, VAL_COL, cols));
- else if (idx.type() == GEO_SPATIAL)
- idxs.add(new GridH2SpatialIndex(tbl, name, cols, KEY_COL, VAL_COL));
- else
- throw new IllegalStateException();
- }
- }
-
- return idxs;
- }
- }
-
- /**
- * Special field set iterator based on database result set.
- */
- private static class FieldsIterator extends GridH2ResultSetIterator<List<IndexingEntity<?>>> {
- /** */
- private static final long serialVersionUID = 0L;
-
- /**
- * @param data Data.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- protected FieldsIterator(ResultSet data) throws IgniteSpiException {
- super(data);
- }
-
- /** {@inheritDoc} */
- @Override protected List<IndexingEntity<?>> createRow() {
- List<IndexingEntity<?>> res = new ArrayList<>(row.length);
-
- for (Object val : row) {
- res.add(val instanceof IndexingEntity ? (IndexingEntity<?>)val :
- new IndexingEntityAdapter<>(val, null));
- }
-
- return res;
- }
- }
-
- /**
- * Special key/value iterator based on database result set.
- */
- private static class KeyValIterator<K, V> extends GridH2ResultSetIterator<IndexingKeyValueRow<K, V>> {
- /** */
- private static final long serialVersionUID = 0L;
-
- /**
- * @param data Data array.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- protected KeyValIterator(ResultSet data) throws IgniteSpiException {
- super(data);
- }
-
- /** {@inheritDoc} */
- @Override protected IndexingKeyValueRow<K, V> createRow() {
- K key = (K)row[0];
- V val = (V)row[1];
-
- return new IndexingKeyValueRowAdapter<>(new IndexingEntityAdapter<>(key, null),
- new IndexingEntityAdapter<>(val, null), null);
- }
- }
-
- /**
- * Field descriptor.
- */
- private static class SqlFieldMetadata implements IndexingFieldMetadata {
- /** */
- private static final long serialVersionUID = 0L;
-
- /** Schema name. */
- private String schemaName;
-
- /** Type name. */
- private String typeName;
-
- /** Name. */
- private String name;
-
- /** Type. */
- private String type;
-
- /**
- * Required by {@link Externalizable}.
- */
- public SqlFieldMetadata() {
- // No-op
- }
-
- /**
- * @param schemaName Schema name.
- * @param typeName Type name.
- * @param name Name.
- * @param type Type.
- */
- SqlFieldMetadata(@Nullable String schemaName, @Nullable String typeName, String name, String type) {
- assert name != null;
- assert type != null;
-
- this.schemaName = schemaName;
- this.typeName = typeName;
- this.name = name;
- this.type = type;
- }
-
- /** {@inheritDoc} */
- @Override public String schemaName() {
- return schemaName;
- }
-
- /** {@inheritDoc} */
- @Override public String typeName() {
- return typeName;
- }
-
- /** {@inheritDoc} */
- @Override public String fieldName() {
- return name;
- }
-
- /** {@inheritDoc} */
- @Override public String fieldTypeName() {
- return type;
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- U.writeString(out, schemaName);
- U.writeString(out, typeName);
- U.writeString(out, name);
- U.writeString(out, type);
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- schemaName = U.readString(in);
- typeName = U.readString(in);
- name = U.readString(in);
- type = U.readString(in);
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(SqlFieldMetadata.class, this);
- }
- }
-
- /**
- * Database schema object.
- */
- private static class Schema extends ConcurrentHashMap8<String, TableDescriptor> {
- /** */
- private static final long serialVersionUID = 0L;
-
- /** */
- private final String spaceName;
-
- /**
- * @param spaceName Space name.
- */
- private Schema(@Nullable String spaceName) {
- this.spaceName = spaceName;
- }
- }
-
- /**
- * Row descriptor.
- */
- private class RowDescriptor implements GridH2RowDescriptor {
- /** */
- private final IndexingTypeDescriptor type;
-
- /** */
- private final String[] fields;
-
- /** */
- private final int[] fieldTypes;
-
- /** */
- private final int keyType;
-
- /** */
- private final int valType;
-
- /** */
- private final Schema schema;
-
- /** */
- private final ClassLoader valClsLdr;
-
- /** */
- private final int keyCols;
-
- /** */
- private final GridUnsafeGuard guard = offheap == null ? null : new GridUnsafeGuard();
-
- /**
- * @param type Type descriptor.
- * @param schema Schema.
- * @param keyAsObj Store key as java object.
- */
- RowDescriptor(IndexingTypeDescriptor type, Schema schema, boolean keyAsObj) {
- assert type != null;
- assert schema != null;
-
- this.type = type;
- this.schema = schema;
-
- keyCols = type.keyFields().size();
-
- valClsLdr = type.valueClass().getClassLoader();
-
- Map<String, Class<?>> allFields = new LinkedHashMap<>();
-
- allFields.putAll(type.keyFields());
- allFields.putAll(type.valueFields());
-
- fields = allFields.keySet().toArray(new String[allFields.size()]);
-
- fieldTypes = new int[fields.length];
-
- Class[] classes = allFields.values().toArray(new Class[fields.length]);
-
- for (int i = 0; i < fieldTypes.length; i++)
- fieldTypes[i] = DataType.getTypeFromClass(classes[i]);
-
- keyType = keyAsObj ? Value.JAVA_OBJECT : DataType.getTypeFromClass(type.keyClass());
- valType = DataType.getTypeFromClass(type.valueClass());
- }
-
- /** {@inheritDoc} */
- @Override public GridUnsafeGuard guard() {
- return guard;
- }
-
- /** {@inheritDoc} */
- @Override public void cache(GridH2KeyValueRowOffheap row) {
- long ptr = row.pointer();
-
- assert ptr > 0 : ptr;
-
- rowCache.put(ptr, row);
- }
-
- /** {@inheritDoc} */
- @Override public void uncache(long ptr) {
- rowCache.remove(ptr);
- }
-
- /** {@inheritDoc} */
- @Override public GridUnsafeMemory memory() {
- return offheap;
- }
-
- /** {@inheritDoc} */
- @Override public GridH2IndexingSpi spi() {
- return GridH2IndexingSpi.this;
- }
-
- /** {@inheritDoc} */
- @Override public GridH2AbstractKeyValueRow createRow(Object key, @Nullable Object val, long expirationTime)
- throws IgniteSpiException {
- try {
- return offheap == null ?
- new GridH2KeyValueRowOnheap(this, key, keyType, val, valType, expirationTime) :
- new GridH2KeyValueRowOffheap(this, key, keyType, val, valType, expirationTime);
- }
- catch (ClassCastException e) {
- throw new IgniteSpiException("Failed to convert key to SQL type. " +
- "Please make sure that you always store each value type with the same key type or disable " +
- "'defaultIndexFixedTyping' property on GridH2IndexingSpi.", e);
- }
- }
-
- /** {@inheritDoc} */
- @Override public Object readFromSwap(Object key) throws GridException {
- IgniteSpiContext ctx = getSpiContext();
-
- return ctx.readValueFromOffheapAndSwap(schema.spaceName, key, valClsLdr);
- }
-
- /** {@inheritDoc} */
- @Override public int valueType() {
- return valType;
- }
-
- /** {@inheritDoc} */
- @Override public int fieldsCount() {
- return fields.length;
- }
-
- /** {@inheritDoc} */
- @Override public int fieldType(int col) {
- return fieldTypes[col];
- }
-
- /** {@inheritDoc} */
- @Override public Object columnValue(Object obj, int col) {
- try {
- return type.value(obj, fields[col]);
- }
- catch (IgniteSpiException e) {
- throw DbException.convert(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override public boolean isKeyColumn(int col) {
- return keyCols > col;
- }
-
- /** {@inheritDoc} */
- @Override public boolean valueToString() {
- return type.valueTextIndex();
- }
-
- /** {@inheritDoc} */
- @Override public GridH2KeyValueRowOffheap createPointer(long ptr) {
- GridH2KeyValueRowOffheap row = rowCache.get(ptr);
-
- if (row != null) {
- assert row.pointer() == ptr : ptr + " " + row.pointer();
-
- return row;
- }
-
- return new GridH2KeyValueRowOffheap(this, ptr);
- }
- }
-
- /**
- * Object serializer.
- */
- private static class H2Serializer implements JavaObjectSerializer {
- /** {@inheritDoc} */
- @Override public byte[] serialize(Object o) throws Exception {
- return localSpi.get().marshaller.marshal(new IndexingEntityAdapter<>(o, null));
- }
-
- /** {@inheritDoc} */
- @Override public Object deserialize(byte[] bytes) throws Exception {
- return localSpi.get().marshaller.unmarshal(bytes).value();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiMBean.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiMBean.java b/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiMBean.java
deleted file mode 100644
index f9cc010..0000000
--- a/modules/indexing/src/main/java/org/gridgain/grid/spi/indexing/h2/GridH2IndexingSpiMBean.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/* @java.file.header */
-
-/* _________ _____ __________________ _____
- * __ ____/___________(_)______ /__ ____/______ ____(_)_______
- * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
- * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
- * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
- */
-
-package org.gridgain.grid.spi.indexing.h2;
-
-import org.apache.ignite.mbean.*;
-import org.apache.ignite.spi.*;
-import org.h2.api.*;
-import org.jetbrains.annotations.*;
-
-/**
- * Management bean for {@link GridH2IndexingSpi}.
- */
-@IgniteMBeanDescription("MBean that provides access to H2 indexing SPI configuration.")
-public interface GridH2IndexingSpiMBean extends IgniteSpiManagementMBean {
- /**
- * Gets if SPI will index primitive key-value pairs by key.
- *
- * @return Flag value.
- */
- @IgniteMBeanDescription("Index primitive key-value pairs by key by default in all schemas.")
- public boolean isDefaultIndexPrimitiveKey();
-
- /**
- * Gets if SPI will index primitive key-value pairs by value. Makes sense only if
- * {@link GridH2IndexingSpi#setDefaultIndexPrimitiveKey(boolean)} set to true.
- *
- * @return Flag value.
- */
- @IgniteMBeanDescription("Index primitive key-value pairs by value by default in all schemas.")
- public boolean isDefaultIndexPrimitiveValue();
-
- /**
- * If false, SPI will store all keys in BINARY form to make it possible to store
- * the same value type with different key types. If true, key type will be converted
- * to respective SQL type if it is possible.
- *
- * @return Flag value.
- */
- @IgniteMBeanDescription("If false, SPI will store all keys in BINARY form, otherwise it will try to convert key " +
- "type to respective SQL type.")
- public boolean isDefaultIndexFixedTyping();
-
- /**
- * Gets maximum amount of memory available to off-heap storage. Possible values are
- * <ul>
- * <li>{@code -1} - Means that off-heap storage is disabled.</li>
- * <li>
- * {@code 0} - GridGain will not limit off-heap storage (it's up to user to properly
- * add and remove entries from cache to ensure that off-heap storage does not grow
- * indefinitely.
- * </li>
- * <li>Any positive value specifies the limit of off-heap storage in bytes.</li>
- * </ul>
- * Default value is {@code -1}, which means that off-heap storage is disabled by default.
- * <p>
- * Use off-heap storage to load gigabytes of data in memory without slowing down
- * Garbage Collection. Essentially in this case you should allocate very small amount
- * of memory to JVM and GridGain will cache most of the data in off-heap space
- * without affecting JVM performance at all.
- *
- * @return Maximum memory in bytes available to off-heap memory space.
- */
- @IgniteMBeanDescription("Maximum off-heap memory for indexes.")
- public long getMaxOffHeapMemory();
-
- /**
- * Gets index write lock wait time in milliseconds. This parameter can affect query performance under high
- * thread contention. Default value is {@code 100}.
- *
- * @return Index write lock wait time in milliseconds.
- */
- @IgniteMBeanDescription("Index write lock wait time in milliseconds.")
- public long getIndexWriteLockWaitTime();
-
- /**
- * Gets maximum allowed off-heap rows cache size in items.
- *
- * @return Maximum allowed off-heap rows cache size.
- */
- @IgniteMBeanDescription("Maximum allowed off-heap rows cache size.")
- public int getMaxOffheapRowsCacheSize();
-
- /**
- * Gets current off-heap rows cache size in items.
- *
- * @return Current off-heap rows cache size.
- */
- @IgniteMBeanDescription("Current off-heap rows cache size.")
- public int getOffheapRowsCacheSize();
-
- /**
- * Gets currently allocated offheap memory.
- *
- * @return Allocated memory in bytes.
- */
- @IgniteMBeanDescription("Allocated off-heap memory for indexes.")
- public long getAllocatedOffHeapMemory();
-
- /**
- * Gets all registered in this SPI spaces comma separated.
- *
- * @return Collection of space names.
- */
- @IgniteMBeanDescription("All registered in this SPI spaces.")
- public String getSpaceNames();
-
- /**
- * Gets the optional search path consisting of space names to search SQL schema objects. Useful for cross cache
- * queries to avoid writing fully qualified table names.
- *
- * @return Array of space names.
- */
- @Nullable public String[] getSearchPath();
-
- /**
- * The flag indicating that {@link JavaObjectSerializer} for H2 database will be set to optimized version.
- *
- * @return Flag value.
- */
- public boolean isUseOptimizedSerializer();
-
- /**
- * Gets script path to be ran against H2 database after opening.
- *
- * @return Script path.
- */
- @Nullable public String getInitialScriptPath();
-
- /**
- * Get query execution time interpreted by SPI as long query for additional handling (e.g. print warning).
- *
- * @return Long query execution time.
- * @see #isLongQueryExplain()
- */
- @IgniteMBeanDescription("Query execution time interpreted by SPI as long query.")
- public long getLongQueryExecutionTimeout();
-
- /**
- * If {@code true}, SPI prints SQL execution plan for long queries (explain SQL query).
- *
- * @return Flag marking SPI should print SQL execution plan for long queries (explain SQL query).
- * @see #getLongQueryExecutionTimeout()
- */
- @IgniteMBeanDescription("If true, SPI will print SQL execution plan for long queries (explain SQL query).")
- public boolean isLongQueryExplain();
-
- /**
- * Defines whether indexing SPI will index by key entries where key and value are primitive types in given space.
- *
- * @param spaceName Space name.
- * @return Flag value.
- */
- @IgniteMBeanDescription("Index by key entries where key and value are primitive types in given space.")
- @IgniteMBeanParametersNames("spaceName")
- @IgniteMBeanParametersDescriptions("Space name.")
- public boolean isIndexPrimitiveKey(@Nullable String spaceName);
-
- /**
- * Defines whether indexing SPI will index by value entries where key and value are primitive types in given space.
- *
- * @param spaceName Space name.
- * @return Flag value.
- */
- @IgniteMBeanDescription("Index by value entries where key and value are primitive types in given space.")
- @IgniteMBeanParametersNames("spaceName")
- @IgniteMBeanParametersDescriptions("Space name.")
- public boolean isIndexPrimitiveValue(@Nullable String spaceName);
-
- /**
- * If {@code false}, SPI will store all keys in BINARY form to make it possible to store
- * the same value type with different key types. If {@code true}, key type will be converted
- * to respective SQL type if it is possible.
- * <p>
- * Setting this value to {@code false} also means that {@code '_key'} column cannot be indexed and
- * cannot participate in query where clauses. The behavior of using '_key' column in where
- * clauses with this flag set to {@code false} is undefined.
- *
- * @param spaceName Space name.
- * @return Flag value.
- */
- @IgniteMBeanDescription("If false, SPI will store all keys in BINARY form, otherwise it will try to convert key " +
- "type to respective SQL type.")
- @IgniteMBeanParametersNames("spaceName")
- @IgniteMBeanParametersDescriptions("Space name.")
- public boolean isIndexFixedTyping(@Nullable String spaceName);
-
- /**
- * If {@code true}, then table name and all column names in 'create table' SQL
- * generated by SPI are escaped with double quotes. This flag should be set if table name of
- * column name is H2 reserved word or is not valid H2 identifier (e.g. contains space or hyphen).
- * <p>
- * Note if this flag is set then table and column name in SQL queries also must be escaped with double quotes.
- *
- * @return Flag value.
- */
- @IgniteMBeanDescription("If true, then table name and all column names in 'create table' SQL generated by " +
- "SPI are escaped with double quotes.")
- public boolean isDefaultEscapeAll();
-
- /**
- * If {@code true}, then table name and all column names in 'create table' SQL
- * generated by SPI are escaped with double quotes. This flag should be set if table name of
- * column name is H2 reserved word or is not valid H2 identifier (e.g. contains space or hyphen).
- * <p>
- * Note if this flag is set then table and column name in SQL queries also must be escaped with double quotes.
- *
- * @param spaceName Space name.
- * @return Flag value.
- */
- @IgniteMBeanDescription("If true, then table name and all column names in 'create table' SQL generated by " +
- "SPI are escaped with double quotes.")
- @IgniteMBeanParametersNames("spaceName")
- @IgniteMBeanParametersDescriptions("Space name.")
- public boolean isEscapeAll(@Nullable String spaceName);
-}
[11/17] incubator-ignite git commit: ignite-qry - merged
Posted by se...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/managers/indexing/GridIndexingManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/managers/indexing/GridIndexingManager.java b/modules/core/src/main/java/org/gridgain/grid/kernal/managers/indexing/GridIndexingManager.java
index 3cbeea1..52cb769 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/managers/indexing/GridIndexingManager.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/managers/indexing/GridIndexingManager.java
@@ -9,82 +9,28 @@
package org.gridgain.grid.kernal.managers.indexing;
-import org.apache.ignite.lang.*;
-import org.apache.ignite.marshaller.*;
-import org.apache.ignite.portables.*;
import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
-import org.gridgain.grid.cache.*;
-import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.*;
-import org.gridgain.grid.kernal.managers.*;
-import org.gridgain.grid.kernal.processors.cache.*;
import org.gridgain.grid.util.*;
-import org.gridgain.grid.util.future.*;
-import org.gridgain.grid.util.lang.*;
-import org.gridgain.grid.util.tostring.*;
-import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
-import org.gridgain.grid.util.worker.*;
-import org.jdk8.backport.*;
-import org.jetbrains.annotations.*;
+import org.gridgain.grid.kernal.managers.*;
+import org.apache.ignite.spi.indexing.*;
-import java.io.*;
-import java.lang.reflect.*;
import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-import static org.apache.ignite.spi.indexing.IndexType.*;
/**
* Manages cache indexing.
*/
-public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
- /** */
- private IgniteMarshaller marsh;
-
- /** Type descriptors. */
- private final ConcurrentMap<TypeId, TypeDescriptor> types = new ConcurrentHashMap8<>();
-
- /** Type descriptors. */
- private final ConcurrentMap<TypeName, TypeDescriptor> typesByName = new ConcurrentHashMap8<>();
-
- /** */
- private final ConcurrentMap<Long, ClassLoader> ldrById = new ConcurrentHashMap8<>();
-
- /** */
- private final ConcurrentMap<ClassLoader, Long> idByLdr = new ConcurrentHashMap8<>();
-
- /** */
- private final AtomicLong ldrIdGen = new AtomicLong();
-
+public class GridIndexingManager extends GridManagerAdapter<GridIndexingSpi> {
/** */
private final GridSpinBusyLock busyLock = new GridSpinBusyLock();
- /** Configuration-declared types. */
- private Map<TypeId, GridCacheQueryTypeMetadata> declaredTypesById;
-
- /** Configuration-declared types. */
- private final Map<TypeName, GridCacheQueryTypeMetadata> declaredTypesByName = new HashMap<>();
-
- /** Portable IDs. */
- private Map<Integer, String> portableIds;
-
- /** Type resolvers per space name. */
- private Map<String, GridCacheQueryTypeResolver> typeResolvers = new HashMap<>();
-
- /** */
- private ExecutorService execSvc;
-
/**
* @param ctx Kernal context.
*/
public GridIndexingManager(GridKernalContext ctx) {
super(ctx, ctx.config().getIndexingSpi());
-
- marsh = ctx.config().getMarshaller();
}
/**
@@ -95,33 +41,10 @@ public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
return;
if (!enabled())
- U.warn(log, "Indexing is disabled (to enable please configure GridH2IndexingSpi).");
-
- IndexingMarshaller m = new IdxMarshaller();
-
- for (IndexingSpi spi : getSpis()) {
- spi.registerMarshaller(m);
-
- for (GridCacheConfiguration cacheCfg : ctx.config().getCacheConfiguration())
- spi.registerSpace(cacheCfg.getName());
- }
-
- execSvc = ctx.config().getExecutorService();
+ U.warn(log, "Indexing is disabled (to enable please configure GridIndexingSpi).");
startSpi();
- for (GridCacheConfiguration ccfg : ctx.config().getCacheConfiguration()){
- GridCacheQueryConfiguration qryCfg = ccfg.getQueryConfiguration();
-
- if (qryCfg != null) {
- for (GridCacheQueryTypeMetadata meta : qryCfg.getTypeMetadata())
- declaredTypesByName.put(new TypeName(ccfg.getName(), meta.getType()), meta);
-
- if (qryCfg.getTypeResolver() != null)
- typeResolvers.put(ccfg.getName(), qryCfg.getTypeResolver());
- }
- }
-
if (log.isDebugEnabled())
log.debug(startInfo());
}
@@ -148,162 +71,22 @@ public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
}
/**
- * Returns number of objects of given type for given space of spi.
- *
- * @param spi SPI Name.
- * @param space Space.
- * @param valType Value type.
- * @return Objects number or -1 if this type is unknown for given SPI and space.
- * @throws GridException If failed.
- */
- public long size(@Nullable String spi, @Nullable String space, Class<?> valType) throws GridException {
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to get space size (grid is stopping).");
-
- try {
- TypeDescriptor desc = types.get(new TypeId(space, valType));
-
- if (desc == null || !desc.registered())
- return -1;
-
- return getSpi(spi).size(space, desc);
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
- * Rebuilds all search indexes of given value type for given space of spi.
- *
- * @param spi SPI name.
- * @param space Space.
- * @param valTypeName Value type name.
- * @return Future that will be completed when rebuilding of all indexes is finished.
- */
- public IgniteFuture<?> rebuildIndexes(@Nullable final String spi, @Nullable final String space, String valTypeName) {
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to rebuild indexes (grid is stopping).");
-
- try {
- return rebuildIndexes(spi, space, typesByName.get(new TypeName(space, valTypeName)));
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
- * @param spi SPI name.
- * @param space Space.
- * @param desc Type descriptor.
- * @return Future that will be completed when rebuilding of all indexes is finished.
- */
- private IgniteFuture<?> rebuildIndexes(@Nullable final String spi, @Nullable final String space,
- @Nullable final TypeDescriptor desc) {
- if (desc == null || !desc.registered())
- return new GridFinishedFuture<Void>(ctx);
-
- final GridWorkerFuture<?> fut = new GridWorkerFuture<Void>();
-
- GridWorker w = new GridWorker(ctx.gridName(), "index-rebuild-worker", log) {
- @Override protected void body() {
- try {
- getSpi(spi).rebuildIndexes(space, desc);
-
- fut.onDone();
- }
- catch (Exception e) {
- fut.onDone(e);
- }
- catch (Throwable e) {
- log.error("Failed to rebuild indexes for type: " + desc.name(), e);
-
- fut.onDone(e);
- }
- }
- };
-
- fut.setWorker(w);
-
- execSvc.execute(w);
-
- return fut;
- }
-
- /**
- * Rebuilds all search indexes for given spi.
- *
- * @param spi SPI name.
- * @return Future that will be completed when rebuilding of all indexes is finished.
- */
- @SuppressWarnings("unchecked")
- public IgniteFuture<?> rebuildAllIndexes(@Nullable String spi) {
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to get space size (grid is stopping).");
-
- try {
- GridCompoundFuture<?, ?> fut = new GridCompoundFuture<Object, Object>(ctx);
-
- for (Map.Entry<TypeId, TypeDescriptor> e : types.entrySet())
- fut.add((IgniteFuture)rebuildIndexes(spi, e.getKey().space, e.getValue()));
-
- fut.markInitialized();
-
- return fut;
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
- * FOR TESTING ONLY
- *
- * @param name SPI Name.
- * @return SPI.
- */
- public IndexingSpi spi(@Nullable String name) {
- if (F.isEmpty(name))
- return getSpis()[0];
-
- for (IndexingSpi s : getSpis()) {
- if (name.equals(s.getName()))
- return s;
- }
-
- throw new GridRuntimeException("Failed to find SPI for name: " + name);
- }
-
- /**
- * @param x Value.
- * @param bytes Serialized value.
- * @param <T> Value type.
- * @return Index entry.
- */
- private <T> IndexingEntity<T> entry(T x, @Nullable byte[] bytes) {
- return new IndexingEntityAdapter<>(x, bytes);
- }
-
- /**
* Writes key-value pair to index.
*
- * @param spi SPI Name.
* @param space Space.
* @param key Key.
- * @param keyBytes Byte array with key data.
* @param val Value.
- * @param valBytes Byte array with value data.
- * @param ver Cache entry version.
* @param expirationTime Expiration time or 0 if never expires.
* @throws GridException In case of error.
*/
@SuppressWarnings("unchecked")
- public <K, V> void store(final String spi, final String space, final K key, @Nullable byte[] keyBytes, final V val,
- @Nullable byte[] valBytes, byte[] ver, long expirationTime) throws GridException {
+ public <K, V> void store(final String space, final K key, final V val, long expirationTime) throws GridException {
assert key != null;
assert val != null;
+ if (!enabled())
+ return;
+
if (!busyLock.enterBusy())
throw new IllegalStateException("Failed to write to index (grid is stopping).");
@@ -311,125 +94,7 @@ public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
if (log.isDebugEnabled())
log.debug("Storing key to cache query index [key=" + key + ", value=" + val + "]");
- final Class<?> valCls = val.getClass();
- final Class<?> keyCls = key.getClass();
-
- TypeId id = null;
-
- GridCacheQueryTypeResolver rslvr = typeResolvers.get(space);
-
- if (rslvr != null) {
- String typeName = rslvr.resolveTypeName(key, val);
-
- if (typeName != null)
- id = new TypeId(space, ctx.portable().typeId(typeName));
- }
-
- if (id == null) {
- if (val instanceof PortableObject) {
- PortableObject portable = (PortableObject)val;
-
- int typeId = portable.typeId();
-
- String typeName = portableName(typeId);
-
- if (typeName == null)
- return;
-
- id = new TypeId(space, typeId);
- }
- else
- id = new TypeId(space, valCls);
- }
-
- TypeDescriptor desc = types.get(id);
-
- if (desc == null) {
- desc = new TypeDescriptor();
-
- TypeDescriptor existing = types.putIfAbsent(id, desc);
-
- if (existing != null)
- desc = existing;
- }
-
- if (!desc.succeeded()) {
- final TypeDescriptor d = desc;
-
- d.init(new Callable<Void>() {
- @Override public Void call() throws Exception {
- d.keyClass(keyCls);
- d.valueClass(valCls);
-
- if (key instanceof PortableObject) {
- PortableObject portableKey = (PortableObject)key;
-
- String typeName = portableName(portableKey.typeId());
-
- if (typeName != null) {
- GridCacheQueryTypeMetadata keyMeta = declaredType(space, portableKey.typeId());
-
- if (keyMeta != null)
- processPortableMeta(true, keyMeta, d);
- }
- }
- else {
- GridCacheQueryTypeMetadata keyMeta = declaredType(space, keyCls.getName());
-
- if (keyMeta == null)
- processAnnotationsInClass(true, d.keyCls, d, null);
- else
- processClassMeta(true, d.keyCls, keyMeta, d);
- }
-
- if (val instanceof PortableObject) {
- PortableObject portableVal = (PortableObject)val;
-
- String typeName = portableName(portableVal.typeId());
-
- if (typeName != null) {
- GridCacheQueryTypeMetadata valMeta = declaredType(space, portableVal.typeId());
-
- d.name(typeName);
-
- if (valMeta != null)
- processPortableMeta(false, valMeta, d);
- }
- }
- else {
- String valTypeName = typeName(valCls);
-
- d.name(valTypeName);
-
- GridCacheQueryTypeMetadata typeMeta = declaredType(space, valCls.getName());
-
- if (typeMeta == null)
- processAnnotationsInClass(false, d.valCls, d, null);
- else
- processClassMeta(false, d.valCls, typeMeta, d);
- }
-
- d.registered(getSpi(spi).registerType(space, d));
-
- typesByName.put(new TypeName(space, d.name()), d);
-
- return null;
- }
- });
- }
-
- if (!desc.registered())
- return;
-
- if (!desc.valueClass().equals(valCls))
- throw new GridException("Failed to update index due to class name conflict" +
- "(multiple classes with same simple name are stored in the same cache) " +
- "[expCls=" + desc.valueClass().getName() + ", actualCls=" + valCls.getName() + ']');
-
- IndexingEntity<K> k = entry(key, keyBytes);
- IndexingEntity<V> v = entry(val, valBytes);
-
- getSpi(spi).store(space, desc, k, v, ver, expirationTime);
+ getSpi().store(space, key, val, expirationTime);
}
finally {
busyLock.leaveBusy();
@@ -437,138 +102,22 @@ public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
}
/**
- * Gets type name by class.
- *
- * @param cls Class.
- * @return Type name.
- */
- public String typeName(Class<?> cls) {
- String typeName = cls.getSimpleName();
-
- // To protect from failure on anonymous classes.
- if (F.isEmpty(typeName)) {
- String pkg = cls.getPackage().getName();
-
- typeName = cls.getName().substring(pkg.length() + (pkg.isEmpty() ? 0 : 1));
- }
-
- if (cls.isArray()) {
- assert typeName.endsWith("[]");
-
- typeName = typeName.substring(0, typeName.length() - 2) + "_array";
- }
-
- return typeName;
- }
-
- /**
- * Gets portable type name by portable ID.
- *
- * @param typeId Type ID.
- * @return Name.
- */
- private String portableName(int typeId) {
- Map<Integer, String> portableIds = this.portableIds;
-
- if (portableIds == null) {
- portableIds = new HashMap<>();
-
- for (GridCacheConfiguration ccfg : ctx.config().getCacheConfiguration()){
- GridCacheQueryConfiguration qryCfg = ccfg.getQueryConfiguration();
-
- if (qryCfg != null) {
- for (GridCacheQueryTypeMetadata meta : qryCfg.getTypeMetadata())
- portableIds.put(ctx.portable().typeId(meta.getType()), meta.getType());
- }
- }
-
- this.portableIds = portableIds;
- }
-
- return portableIds.get(typeId);
- }
-
- /**
- * @param space Space name.
- * @param typeId Type ID.
- * @return Type meta data if it was declared in configuration.
- */
- @Nullable private GridCacheQueryTypeMetadata declaredType(String space, int typeId) {
- Map<TypeId, GridCacheQueryTypeMetadata> declaredTypesById = this.declaredTypesById;
-
- if (declaredTypesById == null) {
- declaredTypesById = new HashMap<>();
-
- for (GridCacheConfiguration ccfg : ctx.config().getCacheConfiguration()){
- GridCacheQueryConfiguration qryCfg = ccfg.getQueryConfiguration();
-
- if (qryCfg != null) {
- for (GridCacheQueryTypeMetadata meta : qryCfg.getTypeMetadata())
- declaredTypesById.put(new TypeId(ccfg.getName(), ctx.portable().typeId(meta.getType())), meta);
- }
- }
-
- this.declaredTypesById = declaredTypesById;
- }
-
- return declaredTypesById.get(new TypeId(space, typeId));
- }
-
- /**
- * @param space Space name.
- * @param typeName Type name.
- * @return Type meta data if it was declared in configuration.
- */
- @Nullable private GridCacheQueryTypeMetadata declaredType(String space, String typeName) {
- return declaredTypesByName.get(new TypeName(space, typeName));
- }
-
- /**
- * @param spi SPI Name.
* @param space Space.
* @param key Key.
- * @param keyBytes Byte array with key value.
- * @return {@code true} if key was found and removed, otherwise {@code false}.
* @throws GridException Thrown in case of any errors.
*/
@SuppressWarnings("unchecked")
- public <K> boolean remove(String spi, String space, K key, @Nullable byte[] keyBytes) throws GridException {
+ public void remove(String space, Object key) throws GridException {
assert key != null;
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to remove from index (grid is stopping).");
-
- try {
- IndexingEntity<K> k = entry(key, keyBytes);
-
- return getSpi(spi).remove(space, k);
- }
- finally {
- busyLock.leaveBusy();
- }
- }
+ if (!enabled())
+ return;
- /**
- * @param spi SPI Name.
- * @param space Space name.
- * @param clause Clause.
- * @param params Parameters collection.
- * @param includeBackups Include or exclude backup entries.
- * @param filters Key and value filters.
- * @return Field rows.
- * @throws GridException If failed.
- */
- public <K, V> IndexingFieldsResult queryFields(@Nullable String spi, @Nullable String space,
- String clause, Collection<Object> params, boolean includeBackups,
- IndexingQueryFilter filters) throws GridException {
if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to execute query (grid is stopping).");
+ throw new IllegalStateException("Failed to remove from index (grid is stopping).");
try {
- IndexingQueryFilter backupFilter = backupsFilter(includeBackups);
-
- return getSpi(spi).queryFields(space, clause, params,
- and(filters, backupFilter));
+ getSpi().remove(space, key);
}
finally {
busyLock.leaveBusy();
@@ -576,103 +125,51 @@ public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
}
/**
- * @param f1 First filter.
- * @param f2 Second filter.
- * @return And filter of the given two.
- */
- @Nullable private static IndexingQueryFilter and(@Nullable final IndexingQueryFilter f1,
- @Nullable final IndexingQueryFilter f2) {
- if (f1 == null)
- return f2;
-
- if (f2 == null)
- return f1;
-
- return new IndexingQueryFilter() {
- @Nullable @Override public <K, V> IgniteBiPredicate<K, V> forSpace(String spaceName) throws GridException {
- final IgniteBiPredicate<K, V> fltr1 = f1.forSpace(spaceName);
- final IgniteBiPredicate<K, V> fltr2 = f2.forSpace(spaceName);
-
- if (fltr1 == null)
- return fltr2;
-
- if (fltr2 == null)
- return fltr1;
-
- return new IgniteBiPredicate<K, V>() {
- @Override public boolean apply(K k, V v) {
- return fltr1.apply(k, v) && fltr2.apply(k, v);
- }
- };
- }
- };
- }
-
- /**
- * @param spi SPI Name.
* @param space Space.
- * @param clause Clause.
* @param params Parameters collection.
- * @param resType Result type.
- * @param includeBackups Include or exclude backup entries.
* @param filters Filters.
- * @param <K> Key type.
- * @param <V> Value type.
- * @return Key/value rows.
+ * @return Query result.
* @throws GridException If failed.
*/
@SuppressWarnings("unchecked")
- public <K, V> GridCloseableIterator<IndexingKeyValueRow<K, V>> query(String spi, String space, String clause,
- Collection<Object> params, String resType, boolean includeBackups,
- IndexingQueryFilter filters) throws GridException {
+ public IgniteSpiCloseableIterator<?> query(String space, Collection<Object> params, GridIndexingQueryFilter filters)
+ throws GridException {
+ if (!enabled())
+ throw new GridException("Indexing SPI is not configured.");
+
if (!busyLock.enterBusy())
throw new IllegalStateException("Failed to execute query (grid is stopping).");
try {
- TypeDescriptor type = typesByName.get(new TypeName(space, resType));
+ final Iterator<?> res = getSpi().query(space, params, filters);
- if (type == null || !type.registered())
+ if (res == null)
return new GridEmptyCloseableIterator<>();
- IndexingQueryFilter backupFilter = backupsFilter(includeBackups);
-
- return new GridSpiCloseableIteratorWrapper<>(getSpi(spi).<K,V>query(space, clause, params, type,
- and(filters, backupFilter)));
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
- * @param spi SPI Name.
- * @param space Space.
- * @param clause Clause.
- * @param resType Result type.
- * @param includeBackups Include or exclude backup entries.
- * @param filters Key and value filters.
- * @param <K> Key type.
- * @param <V> Value type.
- * @return Key/value rows.
- * @throws GridException If failed.
- */
- @SuppressWarnings("unchecked")
- public <K, V> GridCloseableIterator<IndexingKeyValueRow<K, V>> queryText(String spi, String space,
- String clause, String resType, boolean includeBackups,
- IndexingQueryFilter filters) throws GridException {
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to execute query (grid is stopping).");
-
- try {
- TypeDescriptor type = typesByName.get(new TypeName(space, resType));
+ return new IgniteSpiCloseableIterator<Object>() {
+ @Override public void close() throws GridException {
+ if (res instanceof AutoCloseable) {
+ try {
+ ((AutoCloseable)res).close();
+ }
+ catch (Exception e) {
+ throw new GridException(e);
+ }
+ }
+ }
- if (type == null || !type.registered())
- return new GridEmptyCloseableIterator<>();
+ @Override public boolean hasNext() {
+ return res.hasNext();
+ }
- IndexingQueryFilter backupFilter = backupsFilter(includeBackups);
+ @Override public Object next() {
+ return res.next();
+ }
- return new GridSpiCloseableIteratorWrapper<>(getSpi(spi).<K,V>queryText(space, clause, type,
- and(filters, backupFilter)));
+ @Override public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
}
finally {
busyLock.leaveBusy();
@@ -680,47 +177,21 @@ public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
}
/**
- * @param <K> Key type.
- * @param <V> Value type.
- * @return Predicate.
- * @param includeBackups Include backups.
- */
- @SuppressWarnings("unchecked")
- @Nullable private <K, V> IndexingQueryFilter backupsFilter(boolean includeBackups) {
- if (includeBackups)
- return null;
-
- return new IndexingQueryFilter() {
- @Nullable @Override public IgniteBiPredicate<K, V> forSpace(final String spaceName) {
- final GridCacheAdapter<Object, Object> cache = ctx.cache().internalCache(spaceName);
-
- if (cache.context().isReplicated() || cache.configuration().getBackups() == 0)
- return null;
-
- return new IgniteBiPredicate<K, V>() {
- @Override public boolean apply(K k, V v) {
- return cache.context().affinity().primary(ctx.discovery().localNode(), k, -1);
- }
- };
- }
- };
- }
-
- /**
* Will be called when entry for key will be swapped.
*
- * @param spi Spi name.
* @param spaceName Space name.
- * @param swapSpaceName Swap space name.
* @param key key.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
+ * @throws IgniteSpiException If failed.
*/
- public void onSwap(String spi, String spaceName, String swapSpaceName, Object key) throws IgniteSpiException {
+ public void onSwap(String spaceName, Object key) throws IgniteSpiException {
+ if (!enabled())
+ return;
+
if (!busyLock.enterBusy())
throw new IllegalStateException("Failed to process swap event (grid is stopping).");
try {
- getSpi(spi).onSwap(spaceName, swapSpaceName, key);
+ getSpi().onSwap(spaceName, key);
}
finally {
busyLock.leaveBusy();
@@ -730,1163 +201,24 @@ public class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
/**
* Will be called when entry for key will be unswapped.
*
- * @param spi Spi name.
* @param spaceName Space name.
* @param key Key.
* @param val Value.
- * @param valBytes Value bytes.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
+ * @throws IgniteSpiException If failed.
*/
- public void onUnswap(String spi, String spaceName, Object key, Object val, byte[] valBytes)
+ public void onUnswap(String spaceName, Object key, Object val)
throws IgniteSpiException {
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to process swap event (grid is stopping).");
-
- try {
- getSpi(spi).onUnswap(spaceName, key, val, valBytes);
- }
- finally {
- busyLock.leaveBusy();
- }
- }
+ if (!enabled())
+ return;
- /**
- * Removes index tables for all classes belonging to given class loader.
- *
- * @param space Space name.
- * @param ldr Class loader to undeploy.
- * @throws GridException If undeploy failed.
- */
- public void onUndeploy(@Nullable String space, ClassLoader ldr) throws GridException {
if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to process undeploy event (grid is stopping).");
+ throw new IllegalStateException("Failed to process swap event (grid is stopping).");
try {
- try {
- Iterator<Map.Entry<TypeId, TypeDescriptor>> it = types.entrySet().iterator();
-
- while (it.hasNext()) {
- Map.Entry<TypeId, TypeDescriptor> e = it.next();
-
- if (!F.eq(e.getKey().space, space))
- continue;
-
- TypeDescriptor desc = e.getValue();
-
- if (ldr.equals(U.detectClassLoader(desc.valCls)) || ldr.equals(U.detectClassLoader(desc.keyCls))) {
- for (IndexingSpi spi : getSpis()) {
- if (desc.await() && desc.registered())
- spi.unregisterType(e.getKey().space, desc);
- }
-
- it.remove();
- }
- }
- }
- finally {
- Long id = idByLdr.remove(ldr);
-
- if (id != null)
- ldrById.remove(id);
- }
+ getSpi().onUnswap(spaceName, key, val);
}
finally {
busyLock.leaveBusy();
}
}
-
- /**
- * Process annotations for class.
- *
- * @param key If given class relates to key.
- * @param cls Class.
- * @param type Type descriptor.
- * @param parent Parent in case of embeddable.
- * @throws GridException In case of error.
- */
- static void processAnnotationsInClass(boolean key, Class<?> cls, TypeDescriptor type,
- @Nullable ClassProperty parent) throws GridException {
- if (U.isJdk(cls))
- return;
-
- if (parent != null && parent.knowsClass(cls))
- throw new GridException("Recursive reference found in type: " + cls.getName());
-
- if (parent == null) { // Check class annotation at top level only.
- GridCacheQueryTextField txtAnnCls = cls.getAnnotation(GridCacheQueryTextField.class);
-
- if (txtAnnCls != null)
- type.valueTextIndex(true);
-
- GridCacheQueryGroupIndex grpIdx = cls.getAnnotation(GridCacheQueryGroupIndex.class);
-
- if (grpIdx != null)
- type.addIndex(grpIdx.name(), SORTED);
-
- GridCacheQueryGroupIndex.List grpIdxList = cls.getAnnotation(GridCacheQueryGroupIndex.List.class);
-
- if (grpIdxList != null && !F.isEmpty(grpIdxList.value())) {
- for (GridCacheQueryGroupIndex idx : grpIdxList.value())
- type.addIndex(idx.name(), SORTED);
- }
- }
-
- for (Class<?> c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) {
- for (Field field : c.getDeclaredFields()) {
- GridCacheQuerySqlField sqlAnn = field.getAnnotation(GridCacheQuerySqlField.class);
- GridCacheQueryTextField txtAnn = field.getAnnotation(GridCacheQueryTextField.class);
-
- if (sqlAnn != null || txtAnn != null) {
- ClassProperty prop = new ClassProperty(field);
-
- prop.parent(parent);
-
- processAnnotation(key, sqlAnn, txtAnn, field.getType(), prop, type);
-
- type.addProperty(key, prop, true);
- }
- }
-
- for (Method mtd : c.getDeclaredMethods()) {
- GridCacheQuerySqlField sqlAnn = mtd.getAnnotation(GridCacheQuerySqlField.class);
- GridCacheQueryTextField txtAnn = mtd.getAnnotation(GridCacheQueryTextField.class);
-
- if (sqlAnn != null || txtAnn != null) {
- if (mtd.getParameterTypes().length != 0)
- throw new GridException("Getter with GridCacheQuerySqlField " +
- "annotation cannot have parameters: " + mtd);
-
- ClassProperty prop = new ClassProperty(mtd);
-
- prop.parent(parent);
-
- processAnnotation(key, sqlAnn, txtAnn, mtd.getReturnType(), prop, type);
-
- type.addProperty(key, prop, true);
- }
- }
- }
- }
-
- /**
- * Processes annotation at field or method.
- *
- * @param key If given class relates to key.
- * @param sqlAnn SQL annotation, can be {@code null}.
- * @param txtAnn H2 text annotation, can be {@code null}.
- * @param cls Class of field or return type for method.
- * @param prop Current property.
- * @param desc Class description.
- * @throws GridException In case of error.
- */
- static void processAnnotation(boolean key, GridCacheQuerySqlField sqlAnn, GridCacheQueryTextField txtAnn,
- Class<?> cls, ClassProperty prop, TypeDescriptor desc) throws GridException {
- if (sqlAnn != null) {
- processAnnotationsInClass(key, cls, desc, prop);
-
- if (!sqlAnn.name().isEmpty())
- prop.name(sqlAnn.name());
-
- if (sqlAnn.index() || sqlAnn.unique()) {
- String idxName = prop.name() + "_idx";
-
- desc.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
-
- desc.addFieldToIndex(idxName, prop.name(), 0, sqlAnn.descending());
- }
-
- if (!F.isEmpty(sqlAnn.groups())) {
- for (String group : sqlAnn.groups())
- desc.addFieldToIndex(group, prop.name(), 0, false);
- }
-
- if (!F.isEmpty(sqlAnn.orderedGroups())) {
- for (GridCacheQuerySqlField.Group idx : sqlAnn.orderedGroups())
- desc.addFieldToIndex(idx.name(), prop.name(), idx.order(), idx.descending());
- }
- }
-
- if (txtAnn != null)
- desc.addFieldToTextIndex(prop.name());
- }
-
- /**
- * Processes declarative metadata for class.
- *
- * @param key Key or value flag.
- * @param cls Class to process.
- * @param meta Type metadata.
- * @param d Type descriptor.
- * @throws GridException If failed.
- */
- static void processClassMeta(boolean key, Class<?> cls, GridCacheQueryTypeMetadata meta, TypeDescriptor d)
- throws GridException {
- for (Map.Entry<String, Class<?>> entry : meta.getAscendingFields().entrySet()) {
- ClassProperty prop = buildClassProperty(cls, entry.getKey(), entry.getValue());
-
- d.addProperty(key, prop, false);
-
- String idxName = prop.name() + "_idx";
-
- d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
-
- d.addFieldToIndex(idxName, prop.name(), 0, false);
- }
-
- for (Map.Entry<String, Class<?>> entry : meta.getDescendingFields().entrySet()) {
- ClassProperty prop = buildClassProperty(cls, entry.getKey(), entry.getValue());
-
- d.addProperty(key, prop, false);
-
- String idxName = prop.name() + "_idx";
-
- d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
-
- d.addFieldToIndex(idxName, prop.name(), 0, true);
- }
-
- for (String txtIdx : meta.getTextFields()) {
- ClassProperty prop = buildClassProperty(cls, txtIdx, String.class);
-
- d.addProperty(key, prop, false);
-
- d.addFieldToTextIndex(prop.name());
- }
-
- Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps = meta.getGroups();
-
- if (grps != null) {
- for (Map.Entry<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> entry : grps.entrySet()) {
- String idxName = entry.getKey();
-
- LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> idxFields = entry.getValue();
-
- int order = 0;
-
- for (Map.Entry<String, IgniteBiTuple<Class<?>, Boolean>> idxField : idxFields.entrySet()) {
- ClassProperty prop = buildClassProperty(cls, idxField.getKey(), idxField.getValue().get1());
-
- d.addProperty(key, prop, false);
-
- Boolean descending = idxField.getValue().get2();
-
- d.addFieldToIndex(idxName, prop.name(), order, descending != null && descending);
-
- order++;
- }
- }
- }
-
- for (Map.Entry<String, Class<?>> entry : meta.getQueryFields().entrySet()) {
- ClassProperty prop = buildClassProperty(cls, entry.getKey(), entry.getValue());
-
- d.addProperty(key, prop, false);
- }
- }
-
- /**
- * Processes declarative metadata for portable object.
- *
- * @param key Key or value flag.
- * @param meta Declared metadata.
- * @param d Type descriptor.
- * @throws GridException If failed.
- */
- static void processPortableMeta(boolean key, GridCacheQueryTypeMetadata meta, TypeDescriptor d)
- throws GridException {
- for (Map.Entry<String, Class<?>> entry : meta.getAscendingFields().entrySet()) {
- PortableProperty prop = buildPortableProperty(entry.getKey(), entry.getValue());
-
- d.addProperty(key, prop, false);
-
- String idxName = prop.name() + "_idx";
-
- d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
-
- d.addFieldToIndex(idxName, prop.name(), 0, false);
- }
-
- for (Map.Entry<String, Class<?>> entry : meta.getDescendingFields().entrySet()) {
- PortableProperty prop = buildPortableProperty(entry.getKey(), entry.getValue());
-
- d.addProperty(key, prop, false);
-
- String idxName = prop.name() + "_idx";
-
- d.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
-
- d.addFieldToIndex(idxName, prop.name(), 0, true);
- }
-
- for (String txtIdx : meta.getTextFields()) {
- PortableProperty prop = buildPortableProperty(txtIdx, String.class);
-
- d.addProperty(key, prop, false);
-
- d.addFieldToTextIndex(prop.name());
- }
-
- Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps = meta.getGroups();
-
- if (grps != null) {
- for (Map.Entry<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> entry : grps.entrySet()) {
- String idxName = entry.getKey();
-
- LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> idxFields = entry.getValue();
-
- int order = 0;
-
- for (Map.Entry<String, IgniteBiTuple<Class<?>, Boolean>> idxField : idxFields.entrySet()) {
- PortableProperty prop = buildPortableProperty(idxField.getKey(), idxField.getValue().get1());
-
- d.addProperty(key, prop, false);
-
- Boolean descending = idxField.getValue().get2();
-
- d.addFieldToIndex(idxName, prop.name(), order, descending != null && descending);
-
- order++;
- }
- }
- }
-
- for (Map.Entry<String, Class<?>> entry : meta.getQueryFields().entrySet()) {
- PortableProperty prop = buildPortableProperty(entry.getKey(), entry.getValue());
-
- if (!d.props.containsKey(prop.name()))
- d.addProperty(key, prop, false);
- }
- }
-
- /**
- * Builds portable object property.
- *
- * @param pathStr String representing path to the property. May contains dots '.' to identify
- * nested fields.
- * @param resType Result type.
- * @return Portable property.
- */
- static PortableProperty buildPortableProperty(String pathStr, Class<?> resType) {
- String[] path = pathStr.split("\\.");
-
- PortableProperty res = null;
-
- for (String prop : path)
- res = new PortableProperty(prop, res, resType);
-
- return res;
- }
-
- /**
- * @param cls Source type class.
- * @param pathStr String representing path to the property. May contains dots '.' to identify nested fields.
- * @param resType Expected result type.
- * @return Property instance corresponding to the given path.
- * @throws GridException If property cannot be created.
- */
- static ClassProperty buildClassProperty(Class<?> cls, String pathStr, Class<?> resType) throws GridException {
- String[] path = pathStr.split("\\.");
-
- ClassProperty res = null;
-
- for (String prop : path) {
- ClassProperty tmp;
-
- try {
- StringBuilder bld = new StringBuilder("get");
-
- bld.append(prop);
-
- bld.setCharAt(3, Character.toUpperCase(bld.charAt(3)));
-
- tmp = new ClassProperty(cls.getMethod(bld.toString()));
- }
- catch (NoSuchMethodException ignore) {
- try {
- tmp = new ClassProperty(cls.getDeclaredField(prop));
- }
- catch (NoSuchFieldException ignored) {
- throw new GridException("Failed to find getter method or field for property named " +
- "'" + prop + "': " + cls.getName());
- }
- }
-
- tmp.parent(res);
-
- cls = tmp.type();
-
- res = tmp;
- }
-
- if (!U.box(resType).isAssignableFrom(U.box(res.type())))
- throw new GridException("Failed to create property for given path (actual property type is not assignable" +
- " to declared type [path=" + pathStr + ", actualType=" + res.type().getName() +
- ", declaredType=" + resType.getName() + ']');
-
- return res;
- }
-
- /**
- * Gets types for space.
- *
- * @param space Space name.
- * @return Descriptors.
- */
- public Collection<IndexingTypeDescriptor> types(@Nullable String space) {
- Collection<IndexingTypeDescriptor> spaceTypes = new ArrayList<>(
- Math.min(10, types.size()));
-
- for (Map.Entry<TypeId, TypeDescriptor> e : types.entrySet()) {
- TypeDescriptor desc = e.getValue();
-
- if (desc.registered() && F.eq(e.getKey().space, space))
- spaceTypes.add(desc);
- }
-
- return spaceTypes;
- }
-
- /**
- * Gets type for space and type name.
- *
- * @param space Space name.
- * @param typeName Type name.
- * @return Type.
- * @throws GridException If failed.
- */
- public IndexingTypeDescriptor type(@Nullable String space, String typeName) throws GridException {
- TypeDescriptor type = typesByName.get(new TypeName(space, typeName));
-
- if (type == null || !type.registered())
- throw new GridException("Failed to find type descriptor for type name: " + typeName);
-
- return type;
- }
-
- /**
- * @param cls Field type.
- * @return {@code True} if given type is a spatial geometry type based on {@code com.vividsolutions.jts} library.
- * @throws GridException If failed.
- */
- private static boolean isGeometryClass(Class<?> cls) throws GridException {
- Class<?> dataTypeCls;
-
- try {
- dataTypeCls = Class.forName("org.h2.value.DataType");
- }
- catch (ClassNotFoundException ignored) {
- return false; // H2 is not in classpath.
- }
-
- try {
- Method method = dataTypeCls.getMethod("isGeometryClass", Class.class);
-
- return (Boolean)method.invoke(null, cls);
- }
- catch (Exception e) {
- throw new GridException("Failed to invoke 'org.h2.value.DataType.isGeometryClass' method.", e);
- }
- }
-
- /**
- *
- */
- private abstract static class Property {
- /**
- * Gets this property value from the given object.
- *
- * @param x Object with this property.
- * @return Property value.
- * @throws org.apache.ignite.spi.IgniteSpiException If failed.
- */
- public abstract Object value(Object x) throws IgniteSpiException;
-
- /**
- * @return Property name.
- */
- public abstract String name();
-
- /**
- * @return Class member type.
- */
- public abstract Class<?> type();
- }
-
- /**
- * Description of type property.
- */
- private static class ClassProperty extends Property {
- /** */
- private final Member member;
-
- /** */
- private ClassProperty parent;
-
- /** */
- private String name;
-
- /** */
- private boolean field;
-
- /**
- * Constructor.
- *
- * @param member Element.
- */
- ClassProperty(Member member) {
- this.member = member;
-
- name = member instanceof Method && member.getName().startsWith("get") && member.getName().length() > 3 ?
- member.getName().substring(3) : member.getName();
-
- ((AccessibleObject) member).setAccessible(true);
-
- field = member instanceof Field;
- }
-
- /** {@inheritDoc} */
- @Override public Object value(Object x) throws IgniteSpiException {
- if (parent != null)
- x = parent.value(x);
-
- if (x == null)
- return null;
-
- try {
- if (field) {
- Field field = (Field)member;
-
- return field.get(x);
- }
- else {
- Method mtd = (Method)member;
-
- return mtd.invoke(x);
- }
- }
- catch (Exception e) {
- throw new IgniteSpiException(e);
- }
- }
-
- /**
- * @param name Property name.
- */
- public void name(String name) {
- this.name = name;
- }
-
- /** {@inheritDoc} */
- @Override public String name() {
- return name;
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> type() {
- return member instanceof Field ? ((Field)member).getType() : ((Method)member).getReturnType();
- }
-
- /**
- * @param parent Parent property if this is embeddable element.
- */
- public void parent(ClassProperty parent) {
- this.parent = parent;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(ClassProperty.class, this);
- }
-
- /**
- * @param cls Class.
- * @return {@code true} If this property or some parent relates to member of the given class.
- */
- public boolean knowsClass(Class<?> cls) {
- return member.getDeclaringClass() == cls || (parent != null && parent.knowsClass(cls));
- }
- }
-
- /**
- *
- */
- private static class PortableProperty extends Property {
- /** Property name. */
- private String propName;
-
- /** Parent property. */
- private PortableProperty parent;
-
- /** Result class. */
- private Class<?> type;
-
- /**
- * Constructor.
- *
- * @param propName Property name.
- * @param parent Parent property.
- * @param type Result type.
- */
- private PortableProperty(String propName, PortableProperty parent, Class<?> type) {
- this.propName = propName;
- this.parent = parent;
- this.type = type;
- }
-
- /** {@inheritDoc} */
- @Override public Object value(Object obj) throws IgniteSpiException {
- if (parent != null)
- obj = parent.value(obj);
-
- if (obj == null)
- return null;
-
- if (!(obj instanceof PortableObject))
- throw new IgniteSpiException("Non-portable object received as a result of property extraction " +
- "[parent=" + parent + ", propName=" + propName + ", obj=" + obj + ']');
-
- try {
- return ((PortableObject)obj).field(propName);
- }
- catch (PortableException e) {
- throw new IgniteSpiException(e);
- }
- }
-
- /** {@inheritDoc} */
- @Override public String name() {
- return propName;
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> type() {
- return type;
- }
- }
-
- /**
- * Descriptor of type.
- */
- private static class TypeDescriptor implements IndexingTypeDescriptor {
- /** */
- private String name;
-
- /** Value field names and types with preserved order. */
- @GridToStringInclude
- private final Map<String, Class<?>> valFields = new LinkedHashMap<>();
-
- /** */
- @GridToStringExclude
- private final Map<String, Property> props = new HashMap<>();
-
- /** Key field names and types with preserved order. */
- @GridToStringInclude
- private final Map<String, Class<?>> keyFields = new LinkedHashMap<>();
-
- /** */
- @GridToStringInclude
- private final Map<String, IndexDescriptor> indexes = new HashMap<>();
-
- /** */
- private IndexDescriptor fullTextIdx;
-
- /** */
- private Class<?> keyCls;
-
- /** */
- private Class<?> valCls;
-
- /** */
- private boolean valTextIdx;
-
- /** To ensure that type was registered in SPI and only once. */
- private final GridAtomicInitializer<Void> initializer = new GridAtomicInitializer<>();
-
- /** SPI can decide not to register this type. */
- private boolean registered;
-
- /**
- * @param c Initialization callable.
- * @throws GridException In case of error.
- */
- void init(Callable<Void> c) throws GridException {
- initializer.init(c);
- }
-
- /**
- * @return Waits for initialization.
- * @throws GridInterruptedException If thread is interrupted.
- */
- boolean await() throws GridInterruptedException {
- return initializer.await();
- }
-
- /**
- * @return Whether initialization was successfully completed.
- */
- boolean succeeded() {
- return initializer.succeeded();
- }
-
- /**
- * @return {@code True} if type registration in SPI was finished and type was not rejected.
- */
- boolean registered() {
- return initializer.succeeded() && registered;
- }
-
- /**
- * @param registered Sets registered flag.
- */
- void registered(boolean registered) {
- this.registered = registered;
- }
-
- /** {@inheritDoc} */
- @Override public String name() {
- return name;
- }
-
- /**
- * Sets type name.
- *
- * @param name Name.
- */
- void name(String name) {
- this.name = name;
- }
-
- /** {@inheritDoc} */
- @Override public Map<String, Class<?>> valueFields() {
- return valFields;
- }
-
- /** {@inheritDoc} */
- @Override public Map<String, Class<?>> keyFields() {
- return keyFields;
- }
-
- /** {@inheritDoc} */
- @Override public <T> T value(Object obj, String field) throws IgniteSpiException {
- assert obj != null;
- assert field != null;
-
- Property prop = props.get(field);
-
- if (prop == null)
- throw new IgniteSpiException("Failed to find field '" + field + "' in type '" + name + "'.");
-
- return (T)prop.value(obj);
- }
-
- /** {@inheritDoc} */
- @Override public Map<String, org.apache.ignite.spi.indexing.IndexDescriptor> indexes() {
- return Collections.<String, org.apache.ignite.spi.indexing.IndexDescriptor>unmodifiableMap(indexes);
- }
-
- /**
- * Adds index.
- *
- * @param idxName Index name.
- * @param type Index type.
- * @return Index descriptor.
- * @throws GridException In case of error.
- */
- public IndexDescriptor addIndex(String idxName, IndexType type) throws GridException {
- IndexDescriptor idx = new IndexDescriptor(type);
-
- if (indexes.put(idxName, idx) != null)
- throw new GridException("Index with name '" + idxName + "' already exists.");
-
- return idx;
- }
-
- /**
- * Adds field to index.
- *
- * @param idxName Index name.
- * @param field Field name.
- * @param orderNum Fields order number in index.
- * @param descending Sorting order.
- * @throws GridException If failed.
- */
- public void addFieldToIndex(String idxName, String field, int orderNum,
- boolean descending) throws GridException {
- IndexDescriptor desc = indexes.get(idxName);
-
- if (desc == null)
- desc = addIndex(idxName, SORTED);
-
- desc.addField(field, orderNum, descending);
- }
-
- /**
- * Adds field to text index.
- *
- * @param field Field name.
- */
- public void addFieldToTextIndex(String field) {
- if (fullTextIdx == null) {
- fullTextIdx = new IndexDescriptor(FULLTEXT);
-
- indexes.put(null, fullTextIdx);
- }
-
- fullTextIdx.addField(field, 0, false);
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> valueClass() {
- return valCls;
- }
-
- /**
- * Sets value class.
- *
- * @param valCls Value class.
- */
- void valueClass(Class<?> valCls) {
- this.valCls = valCls;
- }
-
- /** {@inheritDoc} */
- @Override public Class<?> keyClass() {
- return keyCls;
- }
-
- /**
- * Set key class.
- *
- * @param keyCls Key class.
- */
- void keyClass(Class<?> keyCls) {
- this.keyCls = keyCls;
- }
-
- /**
- * Adds property to the type descriptor.
- *
- * @param key If given property relates to key.
- * @param prop Property.
- * @param failOnDuplicate Fail on duplicate flag.
- * @throws GridException In case of error.
- */
- public void addProperty(boolean key, Property prop, boolean failOnDuplicate) throws GridException {
- String name = prop.name();
-
- if (props.put(name, prop) != null && failOnDuplicate)
- throw new GridException("Property with name '" + name + "' already exists.");
-
- if (key)
- keyFields.put(name, prop.type());
- else
- valFields.put(name, prop.type());
- }
-
- /** {@inheritDoc} */
- @Override public boolean valueTextIndex() {
- return valTextIdx;
- }
-
- /**
- * Sets if this value should be text indexed.
- *
- * @param valTextIdx Flag value.
- */
- public void valueTextIndex(boolean valTextIdx) {
- this.valTextIdx = valTextIdx;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(TypeDescriptor.class, this);
- }
- }
-
- /**
- * Index descriptor.
- */
- private static class IndexDescriptor implements org.apache.ignite.spi.indexing.IndexDescriptor {
- /** Fields sorted by order number. */
- private final Collection<T2<String, Integer>> fields = new TreeSet<>(
- new Comparator<T2<String, Integer>>() {
- @Override public int compare(T2<String, Integer> o1, T2<String, Integer> o2) {
- if (o1.get2().equals(o2.get2())) // Order is equal, compare field names to avoid replace in Set.
- return o1.get1().compareTo(o2.get1());
-
- return o1.get2() < o2.get2() ? -1 : 1;
- }
- });
-
- /** Fields which should be indexed in descending order. */
- private Collection<String> descendings;
-
- /** */
- private final IndexType type;
-
- /**
- * @param type Type.
- */
- private IndexDescriptor(IndexType type) {
- assert type != null;
-
- this.type = type;
- }
-
- /** {@inheritDoc} */
- @Override public Collection<String> fields() {
- Collection<String> res = new ArrayList<>(fields.size());
-
- for (T2<String, Integer> t : fields)
- res.add(t.get1());
-
- return res;
- }
-
- /** {@inheritDoc} */
- @Override public boolean descending(String field) {
- return descendings != null && descendings.contains(field);
- }
-
- /**
- * Adds field to this index.
- *
- * @param field Field name.
- * @param orderNum Field order number in this index.
- * @param descending Sort order.
- */
- public void addField(String field, int orderNum, boolean descending) {
- fields.add(new T2<>(field, orderNum));
-
- if (descending) {
- if (descendings == null)
- descendings = new HashSet<>();
-
- descendings.add(field);
- }
- }
-
- /** {@inheritDoc} */
- @Override public IndexType type() {
- return type;
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(IndexDescriptor.class, this);
- }
- }
-
- /**
- * Identifying TypeDescriptor by space and value class.
- */
- private static class TypeId {
- /** */
- private final String space;
-
- /** Value type. */
- private final Class<?> valType;
-
- /** Value type ID. */
- private final int valTypeId;
-
- /**
- * Constructor.
- *
- * @param space Space name.
- * @param valType Value type.
- */
- private TypeId(String space, Class<?> valType) {
- assert valType != null;
-
- this.space = space;
- this.valType = valType;
-
- valTypeId = 0;
- }
-
- /**
- * Constructor.
- *
- * @param space Space name.
- * @param valTypeId Value type ID.
- */
- private TypeId(String space, int valTypeId) {
- this.space = space;
- this.valTypeId = valTypeId;
-
- valType = null;
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(Object o) {
- if (this == o)
- return true;
-
- if (o == null || getClass() != o.getClass())
- return false;
-
- TypeId typeId = (TypeId)o;
-
- return (valTypeId == typeId.valTypeId) &&
- (valType != null ? valType == typeId.valType : typeId.valType == null) &&
- (space != null ? space.equals(typeId.space) : typeId.space == null);
- }
-
- /** {@inheritDoc} */
- @Override public int hashCode() {
- return 31 * (space != null ? space.hashCode() : 0) + (valType != null ? valType.hashCode() : valTypeId);
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(TypeId.class, this);
- }
- }
-
- /**
- *
- */
- private static class TypeName {
- /** */
- private final String space;
-
- /** */
- private final String typeName;
-
- /**
- * @param space Space name.
- * @param typeName Type name.
- */
- private TypeName(@Nullable String space, String typeName) {
- assert !F.isEmpty(typeName) : typeName;
-
- this.space = space;
- this.typeName = typeName;
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(Object o) {
- if (this == o)
- return true;
-
- if (o == null || getClass() != o.getClass())
- return false;
-
- TypeName other = (TypeName)o;
-
- return (space != null ? space.equals(other.space) : other.space == null) &&
- typeName.equals(other.typeName);
- }
-
- /** {@inheritDoc} */
- @Override public int hashCode() {
- return 31 * (space != null ? space.hashCode() : 0) + typeName.hashCode();
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(TypeName.class, this);
- }
- }
-
- /**
- * Indexing marshaller which also stores information about class loader and allows lazy unmarshalling.
- */
- private class IdxMarshaller implements IndexingMarshaller {
- /** {@inheritDoc} */
- @Override public <T> IndexingEntity<T> unmarshal(final byte[] bytes) {
- long ldrId = bytes[0] == -1 ? 0 : U.bytesToLong(bytes, 0);
-
- final ClassLoader ldr = ldrId == 0 ? null : ldrById.get(ldrId);
-
- final int off = ldrId == 0 ? 1 : 8;
-
- final int len = bytes.length - off;
-
- return new IndexingEntity<T>() {
- /** */
- private T val;
-
- /** */
- private byte[] valBytes;
-
- @Override public T value() throws IgniteSpiException {
- if (val == null) {
- try {
- val = marsh.unmarshal(new ByteArrayInputStream(bytes, off, len), ldr);
- }
- catch (GridException e) {
- throw new IgniteSpiException(e);
- }
- }
-
- return val;
- }
-
- @Override public byte[] bytes() {
- if (valBytes == null) {
- byte[] bs = new byte[len];
-
- U.arrayCopy(bytes, off, bs, 0, len);
-
- valBytes = bs;
- }
-
- return valBytes;
- }
-
- @Override public boolean hasValue() {
- return val != null;
- }
- };
- }
-
- /** {@inheritDoc} */
- @Override public byte[] marshal(IndexingEntity<?> entity) throws IgniteSpiException {
- Object val = entity.value();
-
- ClassLoader ldr = val.getClass().getClassLoader();
-
- byte[] bytes = entity.bytes();
-
- ByteArrayOutputStream out = new ByteArrayOutputStream(bytes == null ? 128 : bytes.length + 8);
-
- if (ldr == null)
- // In special case of bootstrap class loader ldrId will be one byte -1.
- out.write(-1);
- else {
- Long ldrId;
-
- while ((ldrId = idByLdr.get(ldr)) == null) {
- ldrId = ldrIdGen.incrementAndGet();
-
- if (idByLdr.putIfAbsent(ldr, ldrId) == null) {
- ldrById.put(ldrId, ldr);
-
- break;
- }
- }
-
- try {
- out.write(U.longToBytes(ldrId));
- }
- catch (IOException e) {
- throw new IgniteSpiException(e);
- }
- }
-
- try {
- if (bytes == null)
- marsh.marshal(val, out);
- else
- out.write(bytes);
- }
- catch (Exception e) {
- throw new IgniteSpiException(e);
- }
-
- return out.toByteArray();
- }
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedFieldsQueryFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedFieldsQueryFuture.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedFieldsQueryFuture.java
index 67d8393..6bf1f45 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedFieldsQueryFuture.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedFieldsQueryFuture.java
@@ -11,8 +11,8 @@ package org.gridgain.grid.kernal.processors.cache.query;
import org.apache.ignite.cluster.*;
import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.future.*;
import org.jetbrains.annotations.*;
@@ -29,7 +29,7 @@ public class GridCacheDistributedFieldsQueryFuture
private static final long serialVersionUID = 0L;
/** Meta data future. */
- private final GridFutureAdapter<List<IndexingFieldMetadata>> metaFut;
+ private final GridFutureAdapter<List<GridQueryFieldMetadata>> metaFut;
/**
* Required by {@link Externalizable}.
@@ -61,7 +61,7 @@ public class GridCacheDistributedFieldsQueryFuture
* @param err Error.
* @param finished Finished or not.
*/
- public void onPage(@Nullable UUID nodeId, @Nullable List<IndexingFieldMetadata> metaData,
+ public void onPage(@Nullable UUID nodeId, @Nullable List<GridQueryFieldMetadata> metaData,
@Nullable Collection<Map<String, Object>> data, @Nullable Throwable err, boolean finished) {
if (!metaFut.isDone() && metaData != null)
metaFut.onDone(metaData);
@@ -86,7 +86,7 @@ public class GridCacheDistributedFieldsQueryFuture
}
/** {@inheritDoc} */
- @Override public IgniteFuture<List<IndexingFieldMetadata>> metadata() {
+ @Override public IgniteFuture<List<GridQueryFieldMetadata>> metadata() {
return metaFut;
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedQueryManager.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedQueryManager.java
index ebbfa6c..9306eb3 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedQueryManager.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheDistributedQueryManager.java
@@ -12,11 +12,11 @@ package org.gridgain.grid.kernal.processors.cache.query;
import org.apache.ignite.cluster.*;
import org.apache.ignite.events.*;
import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.managers.eventstorage.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
@@ -432,8 +432,8 @@ public class GridCacheDistributedQueryManager<K, V> extends GridCacheQueryManage
/** {@inheritDoc} */
@Override protected boolean onFieldsPageReady(boolean loc, GridCacheQueryInfo qryInfo,
- @Nullable List<IndexingFieldMetadata> metadata,
- @Nullable Collection<List<IndexingEntity<?>>> entities,
+ @Nullable List<GridQueryFieldMetadata> metadata,
+ @Nullable Collection<?> entities,
@Nullable Collection<?> data,
boolean finished, @Nullable Throwable e) {
assert qryInfo != null;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheFieldsQueryErrorFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheFieldsQueryErrorFuture.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheFieldsQueryErrorFuture.java
index 9834ff8..3da96d7 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheFieldsQueryErrorFuture.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheFieldsQueryErrorFuture.java
@@ -10,8 +10,8 @@
package org.gridgain.grid.kernal.processors.cache.query;
import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.kernal.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.future.*;
import java.util.*;
@@ -40,7 +40,7 @@ public class GridCacheFieldsQueryErrorFuture extends GridCacheQueryErrorFuture<L
/**
* @return Metadata.
*/
- public IgniteFuture<List<IndexingFieldMetadata>> metadata() {
- return new GridFinishedFuture<>(ctx, incMeta ? Collections.<IndexingFieldMetadata>emptyList() : null);
+ public IgniteFuture<List<GridQueryFieldMetadata>> metadata() {
+ return new GridFinishedFuture<>(ctx, incMeta ? Collections.<GridQueryFieldMetadata>emptyList() : null);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalFieldsQueryFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalFieldsQueryFuture.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalFieldsQueryFuture.java
index cc8ed19..5114f3a 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalFieldsQueryFuture.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalFieldsQueryFuture.java
@@ -10,8 +10,8 @@
package org.gridgain.grid.kernal.processors.cache.query;
import org.apache.ignite.lang.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.kernal.processors.cache.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.gridgain.grid.util.future.*;
import org.jetbrains.annotations.*;
@@ -28,7 +28,7 @@ public class GridCacheLocalFieldsQueryFuture
private static final long serialVersionUID = 0L;
/** Meta data future. */
- private final GridFutureAdapter<List<IndexingFieldMetadata>> metaFut;
+ private final GridFutureAdapter<List<GridQueryFieldMetadata>> metaFut;
/**
* Required by {@link Externalizable}.
@@ -57,7 +57,7 @@ public class GridCacheLocalFieldsQueryFuture
* @param err Error.
* @param finished Finished or not.
*/
- public void onPage(@Nullable UUID nodeId, @Nullable List<IndexingFieldMetadata> metaData,
+ public void onPage(@Nullable UUID nodeId, @Nullable List<GridQueryFieldMetadata> metaData,
@Nullable Collection<?> data, @Nullable Throwable err, boolean finished) {
onPage(nodeId, data, err, finished);
@@ -66,7 +66,7 @@ public class GridCacheLocalFieldsQueryFuture
}
/** {@inheritDoc} */
- @Override public IgniteFuture<List<IndexingFieldMetadata>> metadata() {
+ @Override public IgniteFuture<List<GridQueryFieldMetadata>> metadata() {
return metaFut;
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalQueryManager.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalQueryManager.java
index 85cab07..9dd1d7f 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalQueryManager.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheLocalQueryManager.java
@@ -10,9 +10,9 @@
package org.gridgain.grid.kernal.processors.cache.query;
import org.apache.ignite.cluster.*;
-import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.query.*;
+import org.gridgain.grid.kernal.processors.query.*;
import org.jetbrains.annotations.*;
import java.util.*;
@@ -45,8 +45,8 @@ public class GridCacheLocalQueryManager<K, V> extends GridCacheQueryManager<K, V
/** {@inheritDoc} */
@Override protected boolean onFieldsPageReady(boolean loc,
GridCacheQueryInfo qryInfo,
- @Nullable List<IndexingFieldMetadata> metaData,
- @Nullable Collection<List<IndexingEntity<?>>> entities,
+ @Nullable List<GridQueryFieldMetadata> metaData,
+ @Nullable Collection<?> entities,
@Nullable Collection<?> data,
boolean finished,
@Nullable Throwable e) {
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesEx.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesEx.java
index a3fd1c8..803719c 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesEx.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesEx.java
@@ -34,4 +34,11 @@ public interface GridCacheQueriesEx<K, V> extends GridCacheQueries<K, V> {
* @return Created query.
*/
public GridCacheQuery<List<?>> createSqlFieldsQuery(String qry, boolean incMeta);
+
+ /**
+ * Creates SPI query.
+ *
+ * @return Query.
+ */
+ public <R> GridCacheQuery<R> createSpiQuery();
}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesImpl.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesImpl.java
index 98ff5e8..ee02797 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesImpl.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesImpl.java
@@ -10,6 +10,7 @@
package org.gridgain.grid.kernal.processors.cache.query;
import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.indexing.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
@@ -61,7 +62,7 @@ public class GridCacheQueriesImpl<K, V> implements GridCacheQueriesEx<K, V>, Ext
return new GridCacheQueryAdapter<>(ctx,
SQL,
filter(),
- ctx.kernalContext().indexing().typeName(U.box(cls)),
+ ctx.kernalContext().query().typeName(U.box(cls)),
clause,
null,
false,
@@ -105,7 +106,7 @@ public class GridCacheQueriesImpl<K, V> implements GridCacheQueriesEx<K, V>, Ext
return new GridCacheQueryAdapter<>(ctx,
TEXT,
filter(),
- ctx.kernalContext().indexing().typeName(U.box(cls)),
+ ctx.kernalContext().query().typeName(U.box(cls)),
search,
null,
false,
@@ -140,6 +141,22 @@ public class GridCacheQueriesImpl<K, V> implements GridCacheQueriesEx<K, V>, Ext
prj != null && prj.isKeepPortable());
}
+ /**
+ * Query for {@link GridIndexingSpi}.
+ *
+ * @return Query.
+ */
+ public <R> GridCacheQuery<R> createSpiQuery() {
+ return new GridCacheQueryAdapter<>(ctx,
+ SPI,
+ filter(),
+ null,
+ null,
+ null,
+ false,
+ prj != null && prj.isKeepPortable());
+ }
+
/** {@inheritDoc} */
@Override public GridCacheContinuousQuery<K, V> createContinuousQuery() {
return ctx.continuousQueries().createQuery(prj == null ? null : prj.predicate());
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesProxy.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesProxy.java
index d9d40e4..03f1f03 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesProxy.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueriesProxy.java
@@ -154,6 +154,18 @@ public class GridCacheQueriesProxy<K, V> implements GridCacheQueriesEx<K, V>, Ex
}
/** {@inheritDoc} */
+ @Override public <R> GridCacheQuery<R> createSpiQuery() {
+ GridCacheProjectionImpl<K, V> prev = gate.enter(prj);
+
+ try {
+ return delegate.createSpiQuery();
+ }
+ finally {
+ gate.leave(prev);
+ }
+ }
+
+ /** {@inheritDoc} */
@Override public IgniteFuture<?> rebuildIndexes(Class<?> cls) {
GridCacheProjectionImpl<K, V> prev = gate.enter(prj);
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/922a2bab/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryAdapter.java b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryAdapter.java
index 470ed24..dbddd02 100644
--- a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryAdapter.java
+++ b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/query/GridCacheQueryAdapter.java
@@ -12,11 +12,11 @@ package org.gridgain.grid.kernal.processors.cache.query;
import org.apache.ignite.*;
import org.apache.ignite.cluster.*;
import org.apache.ignite.lang.*;
+import org.apache.ignite.plugin.security.*;
import org.gridgain.grid.*;
import org.gridgain.grid.cache.*;
import org.gridgain.grid.cache.query.*;
import org.gridgain.grid.kernal.processors.cache.*;
-import org.apache.ignite.plugin.security.*;
import org.gridgain.grid.util.typedef.*;
import org.gridgain.grid.util.typedef.internal.*;
import org.jetbrains.annotations.*;
@@ -436,7 +436,7 @@ public class GridCacheQueryAdapter<T> implements GridCacheQuery<T> {
boolean loc = nodes.size() == 1 && F.first(nodes).id().equals(cctx.localNodeId());
- if (type == SQL_FIELDS)
+ if (type == SQL_FIELDS || type == SPI)
return (GridCacheQueryFuture<R>)(loc ? qryMgr.queryFieldsLocal(bean) :
qryMgr.queryFieldsDistributed(bean, nodes));
else