You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/04/23 10:47:02 UTC
[1/7] ignite git commit: IGNITE-3028 Implemented generation of fields
aliases with database names in Schema Import Utility.
Repository: ignite
Updated Branches:
refs/heads/ignite-2523-1 2566e0bcf -> be738808d
IGNITE-3028 Implemented generation of fields aliases with database names in Schema Import Utility.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2a64569c
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2a64569c
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2a64569c
Branch: refs/heads/ignite-2523-1
Commit: 2a64569c9beeceff2b48331166b839b38b991462
Parents: e1eb931
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Fri Apr 22 16:08:46 2016 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Fri Apr 22 16:08:46 2016 +0700
----------------------------------------------------------------------
.../ignite/schema/generator/CodeGenerator.java | 26 ++++++++++-
.../ignite/schema/generator/XmlGenerator.java | 45 +++++++++++++++++---
.../schema/parser/DatabaseMetadataParser.java | 6 ++-
.../ignite/schema/ui/SchemaImportApp.java | 30 +++++++++----
.../schema/test/AbstractSchemaImportTest.java | 10 +++--
.../schema/test/generator/XmlGeneratorTest.java | 4 +-
.../apache/ignite/schema/test/model/Objects.txt | 31 +++++++++++++-
.../ignite/schema/test/model/Primitives.txt | 31 +++++++++++++-
.../org/apache/ignite/schema/test/model/Tst.txt | 31 +++++++++++++-
.../schema/test/model/ignite-type-metadata.xml | 42 ++++++++++++++++++
.../test/parser/DbMetadataParserTest.java | 2 +-
11 files changed, 232 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
index 68519d6..3ab0f4e 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
@@ -561,12 +561,13 @@ public class CodeGenerator {
* @param pojos POJO descriptors.
* @param pkg Types package.
* @param includeKeys {@code true} if key fields should be included into value class.
+ * @param generateAliases {@code true} if aliases should be generated for query fields.
* @param outFolder Output folder.
* @param askOverwrite Callback to ask user to confirm file overwrite.
* @throws IOException If generation failed.
*/
public static void snippet(Collection<PojoDescriptor> pojos, String pkg, boolean includeKeys,
- String outFolder, ConfirmCallable askOverwrite) throws IOException {
+ boolean generateAliases, String outFolder, ConfirmCallable askOverwrite) throws IOException {
File pkgFolder = new File(outFolder, pkg.replace('.', File.separatorChar));
File cacheCfg = new File(pkgFolder, "CacheConfig.java");
@@ -663,6 +664,29 @@ public class CodeGenerator {
add2(src, "qryEntity.setFields(fields);");
add0(src, "");
+ // Aliases.
+ if (generateAliases) {
+ Collection<PojoField> aliases = new ArrayList<>();
+
+ for (PojoField field : pojo.fields()) {
+ if (!field.javaName().equalsIgnoreCase(field.dbName()))
+ aliases.add(field);
+ }
+
+ if (!aliases.isEmpty()) {
+ add2(src, "// Aliases for fields.");
+ add2(src, "LinkedHashMap<String, String> aliases = new LinkedHashMap<>();");
+ add0(src, "");
+
+ for (PojoField alias : aliases)
+ add2(src, "aliases.put(\"" + alias.javaName() + "\", \"" + alias.dbName() + "\");");
+
+ add0(src, "");
+ add2(src, "qryEntity.setAliases(aliases);");
+ add0(src, "");
+ }
+ }
+
// Indexes.
Collection<QueryIndex> idxs = pojo.indexes();
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
index a1665ae..bb5a0cb 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
@@ -209,6 +209,31 @@ public class XmlGenerator {
}
/**
+ * Add query field aliases to xml document.
+ *
+ * @param doc XML document.
+ * @param parent Parent XML node.
+ * @param fields Map with fields.
+ */
+ private static void addQueryFieldAliases(Document doc, Node parent, Collection<PojoField> fields) {
+ Collection<PojoField> aliases = new ArrayList<>();
+
+ for (PojoField field : fields) {
+ if (!field.javaName().equalsIgnoreCase(field.dbName()))
+ aliases.add(field);
+ }
+
+ if (!aliases.isEmpty()) {
+ Element prop = addProperty(doc, parent, "aliases", null);
+
+ Element map = addElement(doc, prop, "util:map", "map-class", "java.util.LinkedHashMap");
+
+ for (PojoField alias : aliases)
+ addElement(doc, map, "entry", "key", alias.javaName(), "value", alias.dbName());
+ }
+ }
+
+ /**
* Add indexes to xml document.
*
* @param doc XML document.
@@ -298,8 +323,9 @@ public class XmlGenerator {
* @param parent Parent XML node.
* @param pkg Package fo types.
* @param pojo POJO descriptor.
+ * @param generateAliases {@code true} if aliases should be generated for query fields.
*/
- private static void addQueryEntity(Document doc, Node parent, String pkg, PojoDescriptor pojo) {
+ private static void addQueryEntity(Document doc, Node parent, String pkg, PojoDescriptor pojo, boolean generateAliases) {
Element bean = addBean(doc, parent, QueryEntity.class);
addProperty(doc, bean, "keyType", pkg + "." + pojo.keyClassName());
@@ -310,6 +336,9 @@ public class XmlGenerator {
addQueryFields(doc, bean, fields);
+ if (generateAliases)
+ addQueryFieldAliases(doc, bean, fields);
+
addQueryIndexes(doc, bean, fields, pojo.indexes());
}
@@ -318,12 +347,14 @@ public class XmlGenerator {
*
* @param pkg Package fo types.
* @param pojo POJO descriptor.
+ * @param includeKeys {@code true} if key fields should be included into value class.
+ * @param generateAliases {@code true} if aliases should be generated for query fields.
* @param out File to output result.
* @param askOverwrite Callback to ask user to confirm file overwrite.
*/
- public static void generate(String pkg, PojoDescriptor pojo, boolean includeKeys, File out,
+ public static void generate(String pkg, PojoDescriptor pojo, boolean includeKeys, boolean generateAliases, File out,
ConfirmCallable askOverwrite) {
- generate(pkg, Collections.singleton(pojo), includeKeys, out, askOverwrite);
+ generate(pkg, Collections.singleton(pojo), includeKeys, generateAliases, out, askOverwrite);
}
/**
@@ -331,11 +362,13 @@ public class XmlGenerator {
*
* @param pkg Package fo types.
* @param pojos POJO descriptors.
+ * @param includeKeys {@code true} if key fields should be included into value class.
+ * @param generateAliases {@code true} if aliases should be generated for query fields.
* @param out File to output result.
* @param askOverwrite Callback to ask user to confirm file overwrite.
*/
- public static void generate(String pkg, Collection<PojoDescriptor> pojos, boolean includeKeys, File out,
- ConfirmCallable askOverwrite) {
+ public static void generate(String pkg, Collection<PojoDescriptor> pojos, boolean includeKeys,
+ boolean generateAliases, File out, ConfirmCallable askOverwrite) {
File outFolder = out.getParentFile();
@@ -383,7 +416,7 @@ public class XmlGenerator {
addJdbcPojoStoreFactory(doc, typesItemsElem, pkg, pojo, includeKeys);
for (PojoDescriptor pojo : pojos)
- addQueryEntity(doc, beans, pkg, pojo);
+ addQueryEntity(doc, beans, pkg, pojo, generateAliases);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
index b68f90d..c4490ef 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
@@ -128,8 +128,10 @@ public class DatabaseMetadataParser {
List<PojoDescriptor> res = new ArrayList<>();
- for (String schema : parents.keySet()) {
- PojoDescriptor parent = parents.get(schema);
+ for (Map.Entry<String, PojoDescriptor> item : parents.entrySet()) {
+ String schema = item.getKey();
+ PojoDescriptor parent = item.getValue();
+
Collection<PojoDescriptor> children = childrens.get(schema);
if (!children.isEmpty()) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
index 98ac357..36363dd 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
@@ -222,6 +222,9 @@ public class SchemaImportApp extends Application {
private static final String PREF_POJO_CONSTRUCTOR = "pojo.constructor";
/** */
+ private static final String PREF_GENERATE_ALIASES = "sql.aliases";
+
+ /** */
private static final String PREF_XML_SINGLE = "xml.single";
/** */
@@ -305,6 +308,9 @@ public class SchemaImportApp extends Application {
private CheckBox pojoConstructorCh;
/** */
+ private CheckBox generateAliasesCh;
+
+ /** */
private CheckBox pojoIncludeKeysCh;
/** */
@@ -604,9 +610,11 @@ public class SchemaImportApp extends Application {
final File destFolder = new File(outFolder);
+ final boolean includeKeys = pojoIncludeKeysCh.isSelected();
+
final boolean constructor = pojoConstructorCh.isSelected();
- final boolean includeKeys = pojoIncludeKeysCh.isSelected();
+ final boolean generateAliases = generateAliasesCh.isSelected();
final boolean singleXml = xmlSingleFileCh.isSelected();
@@ -656,16 +664,17 @@ public class SchemaImportApp extends Application {
for (PojoDescriptor pojo : all) {
if (!singleXml)
- XmlGenerator.generate(pkg, pojo, includeKeys, new File(destFolder, pojo.table() + ".xml"),
- askOverwrite);
+ XmlGenerator.generate(pkg, pojo, includeKeys, generateAliases,
+ new File(destFolder, pojo.table() + ".xml"), askOverwrite);
CodeGenerator.pojos(pojo, outFolder, pkg, constructor, includeKeys, askOverwrite);
}
if (singleXml)
- XmlGenerator.generate(pkg, all, includeKeys, new File(outFolder, "ignite-type-metadata.xml"), askOverwrite);
+ XmlGenerator.generate(pkg, all, includeKeys, generateAliases,
+ new File(outFolder, "ignite-type-metadata.xml"), askOverwrite);
- CodeGenerator.snippet(all, pkg, includeKeys, outFolder, askOverwrite);
+ CodeGenerator.snippet(all, pkg, includeKeys, generateAliases, outFolder, askOverwrite);
perceptualDelay(started);
@@ -778,7 +787,7 @@ public class SchemaImportApp extends Application {
String p1 = part1[idx];
String p2 = part2[idx];
- int cmp = p1.matches("\\d+") && p2.matches("\\d+") ? new Integer(p1).compareTo(new Integer(p2)) :
+ int cmp = p1.matches("\\d+") && p2.matches("\\d+") ? Integer.valueOf(p1).compareTo(Integer.valueOf(p2)) :
part1[idx].compareTo(part2[idx]);
if (cmp != 0)
@@ -796,7 +805,7 @@ public class SchemaImportApp extends Application {
while (idx < parts.length) {
String p = parts[idx];
- int cmp = p.matches("\\d+") ? new Integer(p).compareTo(0) : 1;
+ int cmp = p.matches("\\d+") ? Integer.valueOf(p).compareTo(0) : 1;
if (cmp != 0) return left ? cmp : -cmp;
@@ -1228,7 +1237,7 @@ public class SchemaImportApp extends Application {
genPnl.addColumn(35, 35, 35, Priority.NEVER);
genPnl.addRow(100, 100, Double.MAX_VALUE, Priority.ALWAYS);
- genPnl.addRows(7);
+ genPnl.addRows(8);
TableColumn<PojoDescriptor, Boolean> useCol = customColumn("Schema / Table", "use",
"If checked then this table will be used for XML and POJOs generation", PojoDescriptorCell.cellFactory());
@@ -1343,6 +1352,9 @@ public class SchemaImportApp extends Application {
pojoConstructorCh = genPnl.add(checkBox("Generate constructors for POJOs",
"If selected then generate empty and full constructors for POJOs", false), 3);
+ generateAliasesCh = genPnl.add(checkBox("Generate aliases for SQL fields",
+ "If selected then generate aliases for SQL fields with db names", true), 3);
+
xmlSingleFileCh = genPnl.add(checkBox("Write all configurations to a single XML file",
"If selected then all configurations will be saved into the file 'ignite-type-metadata.xml'", true), 3);
@@ -1836,6 +1848,7 @@ public class SchemaImportApp extends Application {
pkgTf.setText(getStringProp(PREF_POJO_PACKAGE, "org.apache.ignite"));
pojoIncludeKeysCh.setSelected(getBoolProp(PREF_POJO_INCLUDE, true));
pojoConstructorCh.setSelected(getBoolProp(PREF_POJO_CONSTRUCTOR, false));
+ generateAliasesCh.setSelected(getBoolProp(PREF_GENERATE_ALIASES, true));
xmlSingleFileCh.setSelected(getBoolProp(PREF_XML_SINGLE, true));
@@ -1901,6 +1914,7 @@ public class SchemaImportApp extends Application {
setStringProp(PREF_POJO_PACKAGE, pkgTf.getText());
setBoolProp(PREF_POJO_INCLUDE, pojoIncludeKeysCh.isSelected());
setBoolProp(PREF_POJO_CONSTRUCTOR, pojoConstructorCh.isSelected());
+ setBoolProp(PREF_GENERATE_ALIASES, generateAliasesCh.isSelected());
setBoolProp(PREF_XML_SINGLE, xmlSingleFileCh.isSelected());
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
index 97f0f87..d4534be 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
@@ -79,7 +79,8 @@ public abstract class AbstractSchemaImportTest extends TestCase {
" dateCol DATE," +
" timeCol TIME," +
" tsCol TIMESTAMP, " +
- " arrCol BINARY(10))");
+ " arrCol BINARY(10)," +
+ " FIELD_WITH_ALIAS VARCHAR(10))");
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS OBJECTS (pk INTEGER PRIMARY KEY, " +
" boolCol BOOLEAN," +
@@ -95,7 +96,8 @@ public abstract class AbstractSchemaImportTest extends TestCase {
" dateCol DATE," +
" timeCol TIME," +
" tsCol TIMESTAMP," +
- " arrCol BINARY(10))");
+ " arrCol BINARY(10)," +
+ " FIELD_WITH_ALIAS VARCHAR(10))");
stmt.executeUpdate("CREATE SCHEMA IF NOT EXISTS TESTSCHEMA");
@@ -113,7 +115,8 @@ public abstract class AbstractSchemaImportTest extends TestCase {
" dateCol DATE," +
" timeCol TIME," +
" tsCol TIMESTAMP, " +
- " arrCol BINARY(10))");
+ " arrCol BINARY(10)," +
+ " FIELD_WITH_ALIAS VARCHAR(10))");
conn.commit();
@@ -144,6 +147,7 @@ public abstract class AbstractSchemaImportTest extends TestCase {
if (!baseLine.equals(generatedLine) && !baseLine.contains(excludePtrn)
&& !generatedLine.contains(excludePtrn)) {
+ System.out.println("Generated file: " + generated.toString());
System.out.println("Expected: " + baseLine);
System.out.println("Generated: " + generatedLine);
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/test/java/org/apache/ignite/schema/test/generator/XmlGeneratorTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/generator/XmlGeneratorTest.java b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/generator/XmlGeneratorTest.java
index 9a1356b..2ed36e9 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/generator/XmlGeneratorTest.java
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/generator/XmlGeneratorTest.java
@@ -40,11 +40,11 @@ public class XmlGeneratorTest extends AbstractSchemaImportTest {
String fileName = "ignite-type-metadata.xml";
- XmlGenerator.generate("org.apache.ignite.schema.test.model", all, true, new File(OUT_DIR_PATH, fileName),
+ XmlGenerator.generate("org.apache.ignite.schema.test.model", all, true, true, new File(OUT_DIR_PATH, fileName),
askOverwrite);
assertTrue("Generated XML file content is differ from expected one",
compareFilesInt(getClass().getResourceAsStream("/org/apache/ignite/schema/test/model/" + fileName),
new File(OUT_DIR_PATH + "/" + fileName), "XML generated by Apache Ignite Schema Import utility"));
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Objects.txt
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Objects.txt b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Objects.txt
index c448ab5..380191b 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Objects.txt
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Objects.txt
@@ -73,6 +73,9 @@ public class Objects implements Serializable {
/** Value for arrcol. */
private Object arrcol;
+ /** Value for fieldWithAlias. */
+ private String fieldWithAlias;
+
/**
* Empty constructor.
*/
@@ -98,7 +101,8 @@ public class Objects implements Serializable {
java.sql.Date datecol,
java.sql.Time timecol,
java.sql.Timestamp tscol,
- Object arrcol
+ Object arrcol,
+ String fieldWithAlias
) {
this.pk = pk;
this.boolcol = boolcol;
@@ -115,6 +119,7 @@ public class Objects implements Serializable {
this.timecol = timecol;
this.tscol = tscol;
this.arrcol = arrcol;
+ this.fieldWithAlias = fieldWithAlias;
}
/**
@@ -387,6 +392,24 @@ public class Objects implements Serializable {
this.arrcol = arrcol;
}
+ /**
+ * Gets fieldWithAlias.
+ *
+ * @return Value for fieldWithAlias.
+ */
+ public String getFieldWithAlias() {
+ return fieldWithAlias;
+ }
+
+ /**
+ * Sets fieldWithAlias.
+ *
+ * @param fieldWithAlias New value for fieldWithAlias.
+ */
+ public void setFieldWithAlias(String fieldWithAlias) {
+ this.fieldWithAlias = fieldWithAlias;
+ }
+
/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o)
@@ -442,6 +465,9 @@ public class Objects implements Serializable {
if (arrcol != null ? !arrcol.equals(that.arrcol) : that.arrcol != null)
return false;
+ if (fieldWithAlias != null ? !fieldWithAlias.equals(that.fieldWithAlias) : that.fieldWithAlias != null)
+ return false;
+
return true;
}
@@ -477,6 +503,8 @@ public class Objects implements Serializable {
res = 31 * res + (arrcol != null ? arrcol.hashCode() : 0);
+ res = 31 * res + (fieldWithAlias != null ? fieldWithAlias.hashCode() : 0);
+
return res;
}
@@ -497,6 +525,7 @@ public class Objects implements Serializable {
", timecol=" + timecol +
", tscol=" + tscol +
", arrcol=" + arrcol +
+ ", fieldWithAlias=" + fieldWithAlias +
"]";
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Primitives.txt
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Primitives.txt b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Primitives.txt
index ef8f902..a07b379 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Primitives.txt
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Primitives.txt
@@ -73,6 +73,9 @@ public class Primitives implements Serializable {
/** Value for arrcol. */
private Object arrcol;
+ /** Value for fieldWithAlias. */
+ private String fieldWithAlias;
+
/**
* Empty constructor.
*/
@@ -98,7 +101,8 @@ public class Primitives implements Serializable {
java.sql.Date datecol,
java.sql.Time timecol,
java.sql.Timestamp tscol,
- Object arrcol
+ Object arrcol,
+ String fieldWithAlias
) {
this.pk = pk;
this.boolcol = boolcol;
@@ -115,6 +119,7 @@ public class Primitives implements Serializable {
this.timecol = timecol;
this.tscol = tscol;
this.arrcol = arrcol;
+ this.fieldWithAlias = fieldWithAlias;
}
/**
@@ -387,6 +392,24 @@ public class Primitives implements Serializable {
this.arrcol = arrcol;
}
+ /**
+ * Gets fieldWithAlias.
+ *
+ * @return Value for fieldWithAlias.
+ */
+ public String getFieldWithAlias() {
+ return fieldWithAlias;
+ }
+
+ /**
+ * Sets fieldWithAlias.
+ *
+ * @param fieldWithAlias New value for fieldWithAlias.
+ */
+ public void setFieldWithAlias(String fieldWithAlias) {
+ this.fieldWithAlias = fieldWithAlias;
+ }
+
/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o)
@@ -442,6 +465,9 @@ public class Primitives implements Serializable {
if (arrcol != null ? !arrcol.equals(that.arrcol) : that.arrcol != null)
return false;
+ if (fieldWithAlias != null ? !fieldWithAlias.equals(that.fieldWithAlias) : that.fieldWithAlias != null)
+ return false;
+
return true;
}
@@ -481,6 +507,8 @@ public class Primitives implements Serializable {
res = 31 * res + (arrcol != null ? arrcol.hashCode() : 0);
+ res = 31 * res + (fieldWithAlias != null ? fieldWithAlias.hashCode() : 0);
+
return res;
}
@@ -501,6 +529,7 @@ public class Primitives implements Serializable {
", timecol=" + timecol +
", tscol=" + tscol +
", arrcol=" + arrcol +
+ ", fieldWithAlias=" + fieldWithAlias +
"]";
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Tst.txt
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Tst.txt b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Tst.txt
index 23d61d0..f1db255 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Tst.txt
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/Tst.txt
@@ -73,6 +73,9 @@ public class Tst implements Serializable {
/** Value for arrcol. */
private Object arrcol;
+ /** Value for fieldWithAlias. */
+ private String fieldWithAlias;
+
/**
* Empty constructor.
*/
@@ -98,7 +101,8 @@ public class Tst implements Serializable {
java.sql.Date datecol,
java.sql.Time timecol,
java.sql.Timestamp tscol,
- Object arrcol
+ Object arrcol,
+ String fieldWithAlias
) {
this.pk = pk;
this.boolcol = boolcol;
@@ -115,6 +119,7 @@ public class Tst implements Serializable {
this.timecol = timecol;
this.tscol = tscol;
this.arrcol = arrcol;
+ this.fieldWithAlias = fieldWithAlias;
}
/**
@@ -387,6 +392,24 @@ public class Tst implements Serializable {
this.arrcol = arrcol;
}
+ /**
+ * Gets fieldWithAlias.
+ *
+ * @return Value for fieldWithAlias.
+ */
+ public String getFieldWithAlias() {
+ return fieldWithAlias;
+ }
+
+ /**
+ * Sets fieldWithAlias.
+ *
+ * @param fieldWithAlias New value for fieldWithAlias.
+ */
+ public void setFieldWithAlias(String fieldWithAlias) {
+ this.fieldWithAlias = fieldWithAlias;
+ }
+
/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o)
@@ -442,6 +465,9 @@ public class Tst implements Serializable {
if (arrcol != null ? !arrcol.equals(that.arrcol) : that.arrcol != null)
return false;
+ if (fieldWithAlias != null ? !fieldWithAlias.equals(that.fieldWithAlias) : that.fieldWithAlias != null)
+ return false;
+
return true;
}
@@ -481,6 +507,8 @@ public class Tst implements Serializable {
res = 31 * res + (arrcol != null ? arrcol.hashCode() : 0);
+ res = 31 * res + (fieldWithAlias != null ? fieldWithAlias.hashCode() : 0);
+
return res;
}
@@ -501,6 +529,7 @@ public class Tst implements Serializable {
", timecol=" + timecol +
", tscol=" + tscol +
", arrcol=" + arrcol +
+ ", fieldWithAlias=" + fieldWithAlias +
"]";
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
index 95706ef..fd14ae2 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
@@ -169,6 +169,14 @@
<property name="javaFieldType" value="java.lang.Object"/>
<property name="javaFieldName" value="arrcol"/>
</bean>
+ <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+ <property name="databaseFieldType">
+ <util:constant static-field="java.sql.Types.VARCHAR"/>
+ </property>
+ <property name="databaseFieldName" value="FIELD_WITH_ALIAS"/>
+ <property name="javaFieldType" value="java.lang.String"/>
+ <property name="javaFieldName" value="fieldWithAlias"/>
+ </bean>
</list>
</property>
</bean>
@@ -311,6 +319,14 @@
<property name="javaFieldType" value="java.lang.Object"/>
<property name="javaFieldName" value="arrcol"/>
</bean>
+ <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+ <property name="databaseFieldType">
+ <util:constant static-field="java.sql.Types.VARCHAR"/>
+ </property>
+ <property name="databaseFieldName" value="FIELD_WITH_ALIAS"/>
+ <property name="javaFieldType" value="java.lang.String"/>
+ <property name="javaFieldName" value="fieldWithAlias"/>
+ </bean>
</list>
</property>
</bean>
@@ -453,6 +469,14 @@
<property name="javaFieldType" value="java.lang.Object"/>
<property name="javaFieldName" value="arrcol"/>
</bean>
+ <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+ <property name="databaseFieldType">
+ <util:constant static-field="java.sql.Types.VARCHAR"/>
+ </property>
+ <property name="databaseFieldName" value="FIELD_WITH_ALIAS"/>
+ <property name="javaFieldType" value="java.lang.String"/>
+ <property name="javaFieldName" value="fieldWithAlias"/>
+ </bean>
</list>
</property>
</bean>
@@ -479,6 +503,12 @@
<entry key="timecol" value="java.sql.Time"/>
<entry key="tscol" value="java.sql.Timestamp"/>
<entry key="arrcol" value="java.lang.Object"/>
+ <entry key="fieldWithAlias" value="java.lang.String"/>
+ </util:map>
+ </property>
+ <property name="aliases">
+ <util:map map-class="java.util.LinkedHashMap">
+ <entry key="fieldWithAlias" value="FIELD_WITH_ALIAS"/>
</util:map>
</property>
<property name="indexes">
@@ -517,6 +547,12 @@
<entry key="timecol" value="java.sql.Time"/>
<entry key="tscol" value="java.sql.Timestamp"/>
<entry key="arrcol" value="java.lang.Object"/>
+ <entry key="fieldWithAlias" value="java.lang.String"/>
+ </util:map>
+ </property>
+ <property name="aliases">
+ <util:map map-class="java.util.LinkedHashMap">
+ <entry key="fieldWithAlias" value="FIELD_WITH_ALIAS"/>
</util:map>
</property>
<property name="indexes">
@@ -555,6 +591,12 @@
<entry key="timecol" value="java.sql.Time"/>
<entry key="tscol" value="java.sql.Timestamp"/>
<entry key="arrcol" value="java.lang.Object"/>
+ <entry key="fieldWithAlias" value="java.lang.String"/>
+ </util:map>
+ </property>
+ <property name="aliases">
+ <util:map map-class="java.util.LinkedHashMap">
+ <entry key="fieldWithAlias" value="FIELD_WITH_ALIAS"/>
</util:map>
</property>
<property name="indexes">
http://git-wip-us.apache.org/repos/asf/ignite/blob/2a64569c/modules/schema-import/src/test/java/org/apache/ignite/schema/test/parser/DbMetadataParserTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/parser/DbMetadataParserTest.java b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/parser/DbMetadataParserTest.java
index a954029..f918012 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/parser/DbMetadataParserTest.java
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/parser/DbMetadataParserTest.java
@@ -66,7 +66,7 @@ public class DbMetadataParserTest extends AbstractSchemaImportTest {
List<PojoField> fields = type.fields();
- assertEquals("Value type should have 15 fields", 15, fields.size());
+ assertEquals("Value type should have 15 fields", 16, fields.size());
Iterator<PojoField> fieldsIt = fields.iterator();
[2/7] ignite git commit: IGNITE-3019 Implement config variations test
for IgniteCompute
Posted by vo...@apache.org.
IGNITE-3019 Implement config variations test for IgniteCompute
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a6de16db
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a6de16db
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a6de16db
Branch: refs/heads/ignite-2523-1
Commit: a6de16db817e0e5f72219ae1fb993392eff8e09c
Parents: 2a64569
Author: sboikov <sb...@gridgain.com>
Authored: Fri Apr 22 16:44:39 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Apr 22 16:44:39 2016 +0300
----------------------------------------------------------------------
...gniteComputeConfigVariationsFullApiTest.java | 2009 ++++++++++++++++++
.../configvariations/ConfigVariations.java | 2 +-
.../IgniteConfigVariationsAbstractTest.java | 43 +-
...teBasicConfigVariationsFullApiTestSuite.java | 72 +
4 files changed, 2124 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6de16db/modules/core/src/test/java/org/apache/ignite/internal/processors/compute/IgniteComputeConfigVariationsFullApiTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/compute/IgniteComputeConfigVariationsFullApiTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/compute/IgniteComputeConfigVariationsFullApiTest.java
new file mode 100644
index 0000000..81cdb15
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/compute/IgniteComputeConfigVariationsFullApiTest.java
@@ -0,0 +1,2009 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.compute;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import javax.cache.configuration.Factory;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCompute;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryReader;
+import org.apache.ignite.binary.BinaryWriter;
+import org.apache.ignite.binary.Binarylizable;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobAdapter;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeTaskFuture;
+import org.apache.ignite.compute.ComputeTaskSplitAdapter;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.lang.IgniteClosure;
+import org.apache.ignite.lang.IgniteReducer;
+import org.apache.ignite.lang.IgniteRunnable;
+import org.apache.ignite.testframework.junits.IgniteConfigVariationsAbstractTest;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
+
+/**
+ * Full API compute test.
+ */
+@SuppressWarnings("unchecked")
+public class IgniteComputeConfigVariationsFullApiTest extends IgniteConfigVariationsAbstractTest {
+ /** Max job count. */
+ private static final int MAX_JOB_COUNT = 10;
+
+ /** Test cache name. */
+ private static final String CACHE_NAME = "test";
+
+ /** */
+ private static final String STR_VAL = "string value";
+
+ /** */
+ private static final Object[] ARRAY_VAL = {"str0", "str1", "str2"};
+
+ /** Job factories. */
+ private static final JobFactory[] jobFactories = new JobFactory[] {
+ new JobFactory(EchoJob.class),
+ new JobFactory(EchoJobExternalizable.class),
+ new JobFactory(EchoJobBinarylizable.class)
+ };
+
+ /** Closure factories. */
+ private static final Factory[] closureFactories = new Factory[] {
+ new JobFactory(EchoClosure.class),
+ new JobFactory(EchoClosureExternalizable.class),
+ new JobFactory(EchoClosureBinarylizable.class)
+ };
+
+ /** Callable factories. */
+ private static final Factory[] callableFactories = new Factory[] {
+ new JobFactory(EchoCallable.class),
+ new JobFactory(EchoCallableExternalizable.class),
+ new JobFactory(EchoCallableBinarylizable.class)
+ };
+
+ /** Runnable factories. */
+ private static final Factory[] runnableFactories = new Factory[] {
+ new JobFactory(ComputeTestRunnable.class),
+ new JobFactory(ComputeTestRunnableExternalizable.class),
+ new JobFactory(ComputeTestRunnableBinarylizable.class)
+ };
+
+ /**
+ * @param expCnt Expected count.
+ * @param results Results.
+ * @param dataCls Data class.
+ */
+ private static void checkResultsClassCount(final int expCnt, final Collection<Object> results,
+ final Class dataCls) {
+ int cnt = 0;
+
+ for (Object o : results) {
+ if ((o != null) && dataCls.equals(o.getClass()))
+ ++cnt;
+ }
+
+ assertEquals("Count of the result objects' type mismatch (null values are filtered)", expCnt, cnt);
+ }
+
+ /**
+ * @return Expected valid result.
+ */
+ private Collection<Object> createGoldenResults() {
+ Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i)
+ results.add(value(i - 1));
+
+ return results;
+ }
+
+ /**
+ * @param msg Message.
+ * @param exp Expected.
+ * @param act Action.
+ */
+ private <E> void assertCollectionsEquals(String msg, Collection<E> exp, Collection<E> act) {
+ assertEquals(msg + "; Size are different", exp.size(), act.size());
+
+ for (Object o : exp) {
+ if (!act.contains(o)) {
+ error("Expected: " + exp.toString());
+ error("Actual: " + act.toString());
+
+ assertTrue(msg + String.format("; actual collection doesn't contain the object [%s]", o), false);
+ }
+ }
+ }
+
+ /**
+ * The test's wrapper provides variations of the argument data model and user factories. The test is launched {@code
+ * factories.length * DataMode.values().length} times with each datamodel and each factory.
+ *
+ * @param test Test.
+ * @param factories various factories
+ * @throws Exception If failed.
+ */
+ protected void runTest(final Factory[] factories, final ComputeTest test) throws Exception {
+ runInAllDataModes(new TestRunnable() {
+ @Override public void run() throws Exception {
+ for (int i = 0; i < factories.length; i++) {
+ Factory factory = factories[i];
+
+ info("Running test with jobs model: " + factory.create().getClass().getSimpleName());
+
+ if (i != 0)
+ beforeTest();
+
+ try {
+ test.test(factory, grid(testedNodeIdx));
+ }
+ finally {
+ if (i + 1 != factories.length)
+ afterTest();
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testExecuteTaskClass() throws Exception {
+ runTest(jobFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ // Begin with negative to check 'null' value in the test.
+ final int[] i = {-1};
+
+ List<Object> results = ignite.compute().execute(
+ TestTask.class,
+ new T2<>((Factory<ComputeJobAdapter>)factory,
+ (Factory<Object>)new Factory<Object>() {
+ @Override public Object create() {
+ return value(i[0]++);
+ }
+ }));
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testExecuteTask() throws Exception {
+ runTest(jobFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ // Begin with negative to check 'null' value in the test.
+ final int[] i = {-1};
+
+ List<Object> results = ignite.compute().execute(new TestTask(),
+ new T2<>((Factory<ComputeJobAdapter>)factory,
+ (Factory<Object>)new Factory<Object>() {
+ @Override public Object create() {
+ return value(i[0]++);
+ }
+ }));
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testBroadcastClosure() throws Exception {
+ runTest(closureFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ final Collection<Object> resultsAllNull = ignite.compute()
+ .broadcast((IgniteClosure<Object, Object>)factory.create(), null);
+
+ assertEquals("Result's size mismatch: job must be run on all server nodes",
+ gridCount() - clientsCount(), resultsAllNull.size());
+
+ for (Object o : resultsAllNull)
+ assertNull("All results must be null", o);
+
+ Collection<Object> resultsNotNull = ignite.compute()
+ .broadcast((IgniteClosure<Object, Object>)factory.create(), value(0));
+
+ checkResultsClassCount(gridCount() - clientsCount(), resultsNotNull, value(0).getClass());
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testBroadcastCallable() throws Exception {
+ runTest(callableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ EchoCallable job = (EchoCallable)factory.create();
+ job.setArg(null);
+
+ final Collection<Object> resultsAllNull = ignite.compute()
+ .broadcast(job);
+
+ assertEquals("Result's size mismatch: job must be run on all server nodes",
+ gridCount() - clientsCount(), resultsAllNull.size());
+
+ for (Object o : resultsAllNull)
+ assertNull("All results must be null", o);
+
+ job.setArg(value(0));
+ Collection<Object> resultsNotNull = ignite.compute()
+ .broadcast(job);
+
+ checkResultsClassCount(gridCount() - clientsCount(), resultsNotNull, value(0).getClass());
+ for (Object o : resultsNotNull)
+ assertEquals("Invalid broadcast results", value(0), o);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testBroadcastRunnable() throws Exception {
+ runTest(runnableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ IgniteRunnable job = (IgniteRunnable)factory.create();
+
+ ignite.compute().broadcast(job);
+ // All checks are inside the run() method of the job.
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testRun() throws Exception {
+ runTest(runnableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ IgniteRunnable job = (IgniteRunnable)factory.create();
+
+ ignite.compute().run(job);
+ // All checks are inside the run() method of the job.
+
+ Collection<IgniteRunnable> jobs = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i)
+ jobs.add((IgniteRunnable)factory.create());
+
+ ignite.compute().run(jobs);
+ // All checks are inside the run() method of the job.
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testApplyAsync() throws Exception {
+ runTest(closureFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ final IgniteCompute comp = ignite.compute().withAsync();
+
+ Collection<ComputeTaskFuture<Object>> futures = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ // value(i - 1): use negative argument of the value method to generate nullong value.
+ comp.apply((IgniteClosure<Object, Object>)factory.create(), value(i - 1));
+
+ futures.add(comp.future());
+ }
+
+ // Wait for results.
+ Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (ComputeTaskFuture<Object> future : futures)
+ results.add(future.get());
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testApplySync() throws Exception {
+ runTest(closureFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ // value(i - 1): use negative argument of the value method to generate nullong value.
+ results.add(ignite.compute().apply((IgniteClosure<Object, Object>)factory.create(), value(i - 1)));
+ }
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testApplyForCollection() throws Exception {
+ runTest(closureFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ Collection<TestObject> params = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ // value(i - 1): use negative argument of the value method to generate nullong value.
+ // Use type casting to avoid ambiguous for apply(Callable, Object) vs apply(Callable, Collection<Object>).
+ params.add((TestObject)value(i - 1));
+ }
+
+ Collection<Object> results = ignite.compute()
+ .apply((IgniteClosure<TestObject, Object>)factory.create(), params);
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testApplyForCollectionWithReducer() throws Exception {
+ runTest(closureFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ Collection<Object> params = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ // value(i - 1): use negative argument of the value method to generate nullong value.
+ params.add(value(i - 1));
+ }
+
+ boolean res = ignite.compute()
+ .apply((IgniteClosure<Object, Object>)factory.create(), params, new IgniteReducer<Object, Boolean>() {
+
+ private Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+
+ @Override public boolean collect(@Nullable Object o) {
+ results.add(o);
+ return true;
+ }
+
+ @Override public Boolean reduce() {
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ return true;
+ }
+ });
+ assertTrue(res);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCallAsync() throws Exception {
+ runTest(callableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ final IgniteCompute comp = ignite.compute().withAsync();
+
+ Collection<ComputeTaskFuture<Object>> futures = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ EchoCallable job = (EchoCallable)factory.create();
+ job.setArg(value(i - 1));
+
+ comp.call(job);
+ futures.add(comp.future());
+ }
+
+ // Wait for results.
+ Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+ for (ComputeTaskFuture<Object> future : futures)
+ results.add(future.get());
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCallSync() throws Exception {
+ runTest(callableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ EchoCallable job = (EchoCallable)factory.create();
+ job.setArg(value(i - 1));
+ results.add(ignite.compute().call(job));
+ }
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCallCollection() throws Exception {
+ runTest(callableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ Collection<EchoCallable> jobs = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ EchoCallable job = (EchoCallable)factory.create();
+ job.setArg(value(i - 1));
+ jobs.add(job);
+ }
+
+ Collection<Object> results = ignite.compute().call(jobs);
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCallCollectionWithReducer() throws Exception {
+ runTest(callableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ Collection<EchoCallable> jobs = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ EchoCallable job = (EchoCallable)factory.create();
+ job.setArg(value(i - 1));
+ jobs.add(job);
+ }
+
+ boolean res = ignite.compute().call(jobs, new IgniteReducer<Object, Boolean>() {
+ private Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+
+ @Override public boolean collect(@Nullable Object o) {
+ results.add(o);
+ return true;
+ }
+
+ @Override public Boolean reduce() {
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ return true;
+ }
+ });
+
+ assertTrue(res);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDummyAffinityCall() throws Exception {
+ runTest(callableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ ignite.getOrCreateCache(CACHE_NAME);
+
+ final IgniteCompute comp = ignite.compute();
+
+ Collection<Object> results = new ArrayList<>(MAX_JOB_COUNT);
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ EchoCallable job = (EchoCallable)factory.create();
+
+ job.setArg(value(i - 1));
+
+ results.add(comp.affinityCall("test", key(0), job));
+ }
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDummyAffinityRun() throws Exception {
+ runTest(runnableFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ ignite.getOrCreateCache(CACHE_NAME);
+
+ final IgniteCompute comp = ignite.compute();
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ IgniteRunnable job = (IgniteRunnable)factory.create();
+
+ comp.affinityRun("test", key(0), job);
+ }
+ }
+ });
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDeployExecuteByName() throws Exception {
+ runTest(jobFactories, new ComputeTest() {
+ @Override public void test(Factory factory, Ignite ignite) throws Exception {
+ final int[] i = {-1};
+
+ final IgniteCompute comp = ignite.compute();
+
+ comp.localDeployTask(TestTask.class, TestTask.class.getClassLoader());
+
+ List<Object> results = ignite.compute().execute(
+ TestTask.class.getName(),
+ new T2<>((Factory<ComputeJobAdapter>)factory,
+ (Factory<Object>)new Factory<Object>() {
+ @Override public Object create() {
+ return value(i[0]++);
+ }
+ }));
+
+ checkResultsClassCount(MAX_JOB_COUNT - 1, results, value(0).getClass());
+ assertCollectionsEquals("Results value mismatch", createGoldenResults(), results);
+
+ comp.undeployTask(TestTask.class.getName());
+ }
+ });
+ }
+
+ /**
+ * Override the base method to return {@code null} value in case the valId is negative.
+ */
+ @Nullable @Override public Object value(int valId) {
+ if (valId < 0)
+ return null;
+
+ return super.value(valId);
+ }
+
+ /**
+ *
+ */
+ enum TestJobEnum {
+ /** */
+ VALUE_0,
+ /** */
+ VALUE_1,
+ /** */
+ VALUE_2
+ }
+
+ /**
+ *
+ */
+ public interface ComputeTest {
+ /**
+ * @param factory Factory.
+ * @param ignite Ignite instance to use.
+ * @throws Exception If failed.
+ */
+ public void test(Factory factory, Ignite ignite) throws Exception;
+ }
+
+ /**
+ * Creates set of jobs.
+ */
+ static class TestTask
+ extends ComputeTaskSplitAdapter<T2<Factory<ComputeJobAdapter>, Factory<Object>>, List<Object>> {
+ /** {@inheritDoc} */
+ @Override protected Collection<? extends ComputeJob> split(int gridSize,
+ T2<Factory<ComputeJobAdapter>, Factory<Object>> factoriesJobAndArg) throws IgniteException {
+ Collection<ComputeJob> jobs = new HashSet<>();
+
+ for (int i = 0; i < MAX_JOB_COUNT; ++i) {
+ ComputeJobAdapter job = factoriesJobAndArg.get1().create();
+
+ job.setArguments(factoriesJobAndArg.get2().create());
+ jobs.add(job);
+ }
+
+ return jobs;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public List<Object> reduce(List<ComputeJobResult> results) throws IgniteException {
+ List<Object> ret = new ArrayList<>(results.size());
+
+ for (ComputeJobResult result : results)
+ ret.add(result.getData());
+
+ return ret;
+ }
+ }
+
+ /**
+ * Echo job, serializable object. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoJob extends ComputeJobAdapter {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor (required by ReflectionFactory).
+ */
+ public EchoJob() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoJob(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal, float fltVal,
+ double dblVal,
+ String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public Object execute() {
+ checkState();
+
+ return argument(0);
+ }
+
+ /**
+ * Check the object state after serialization / deserialization
+ */
+ protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Echo job, externalizable. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoJobExternalizable extends EchoJob implements Externalizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor (required by {@link Externalizable}).
+ */
+ public EchoJobExternalizable() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoJobExternalizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(argument(0));
+
+ JobUtils.writeJobState(out, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ setArguments(in.readObject());
+
+ isVal = in.readBoolean();
+ bVal = in.readByte();
+ cVal = in.readChar();
+ sVal = in.readShort();
+ intVal = in.readInt();
+ lVal = in.readLong();
+ fltVal = in.readFloat();
+ dblVal = in.readDouble();
+ strVal = (String)in.readObject();
+ arrVal = (Object[])in.readObject();
+ eVal = (TestJobEnum)in.readObject();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Echo job, externalizable. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoJobBinarylizable extends EchoJob implements Binarylizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor (required by ReflectionFactory).
+ */
+ public EchoJobBinarylizable() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoJobBinarylizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+ writer.writeObject("arg", argument(0));
+
+ JobUtils.writeJobState(writer, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+ Object arg = reader.readObject("arg");
+
+ setArguments(arg);
+
+ isVal = reader.readBoolean("isVal");
+ bVal = reader.readByte("bVal");
+ cVal = reader.readChar("cVal");
+ sVal = reader.readShort("sVal");
+ intVal = reader.readInt("intVal");
+ lVal = reader.readLong("lVal");
+ fltVal = reader.readFloat("fltVal");
+ dblVal = reader.readDouble("dblVal");
+ strVal = reader.readString("strVal");
+ arrVal = reader.readObjectArray("arrVal");
+ eVal = reader.readEnum("eVal");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Echo job, serializable object. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoClosure implements IgniteClosure<Object, Object> {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor.
+ */
+ public EchoClosure() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoClosure(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal, float fltVal,
+ double dblVal,
+ String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Object apply(Object arg) {
+ checkState();
+
+ return arg;
+ }
+
+ /**
+ * Check the object state after serialization / deserialization
+ */
+ protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Echo closure, externalizable. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoClosureExternalizable extends EchoClosure implements Externalizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor (required by Externalizable).
+ */
+ public EchoClosureExternalizable() {
+ // No-op
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoClosureExternalizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ JobUtils.writeJobState(out, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ isVal = in.readBoolean();
+ bVal = in.readByte();
+ cVal = in.readChar();
+ sVal = in.readShort();
+ intVal = in.readInt();
+ lVal = in.readLong();
+ fltVal = in.readFloat();
+ dblVal = in.readDouble();
+ strVal = (String)in.readObject();
+ arrVal = (Object[])in.readObject();
+ eVal = (TestJobEnum)in.readObject();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Echo closure, externalizable. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoClosureBinarylizable extends EchoClosure implements Binarylizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoClosureBinarylizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+ JobUtils.writeJobState(writer, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+ isVal = reader.readBoolean("isVal");
+ bVal = reader.readByte("bVal");
+ cVal = reader.readChar("cVal");
+ sVal = reader.readShort("sVal");
+ intVal = reader.readInt("intVal");
+ lVal = reader.readLong("lVal");
+ fltVal = reader.readFloat("fltVal");
+ dblVal = reader.readDouble("dblVal");
+ strVal = reader.readString("strVal");
+ arrVal = reader.readObjectArray("arrVal");
+ eVal = reader.readEnum("eVal");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Test callable, serializable object. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoCallable implements IgniteCallable<Object> {
+ /** */
+ protected Object arg;
+
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor.
+ */
+ public EchoCallable() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoCallable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal, float fltVal,
+ double dblVal,
+ String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * @param arg Argument.
+ */
+ void setArg(@Nullable Object arg) {
+ this.arg = arg;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public Object call() throws Exception {
+ checkState();
+
+ return arg;
+ }
+
+ /**
+ * Check the object state after serialization / deserialization
+ */
+ protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Echo callable, externalizable object. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoCallableExternalizable extends EchoCallable implements Externalizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor.
+ */
+ public EchoCallableExternalizable() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoCallableExternalizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(arg);
+
+ JobUtils.writeJobState(out, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ arg = in.readObject();
+
+ isVal = in.readBoolean();
+ bVal = in.readByte();
+ cVal = in.readChar();
+ sVal = in.readShort();
+ intVal = in.readInt();
+ lVal = in.readLong();
+ fltVal = in.readFloat();
+ dblVal = in.readDouble();
+ strVal = (String)in.readObject();
+ arrVal = (Object[])in.readObject();
+ eVal = (TestJobEnum)in.readObject();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Echo callable, binarylizable object. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class EchoCallableBinarylizable extends EchoCallable implements Binarylizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor.
+ */
+ public EchoCallableBinarylizable() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public EchoCallableBinarylizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+ writer.writeObject("arg", arg);
+
+ JobUtils.writeJobState(writer, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+ arg = reader.readObject("arg");
+
+ isVal = reader.readBoolean("isVal");
+ bVal = reader.readByte("bVal");
+ cVal = reader.readChar("cVal");
+ sVal = reader.readShort("sVal");
+ intVal = reader.readInt("intVal");
+ lVal = reader.readLong("lVal");
+ fltVal = reader.readFloat("fltVal");
+ dblVal = reader.readDouble("dblVal");
+ strVal = reader.readString("strVal");
+ arrVal = reader.readObjectArray("arrVal");
+ eVal = reader.readEnum("eVal");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Test runnable, serializable object. All fields are used only for serialization check.
+ */
+ @SuppressWarnings({"PublicInnerClass"})
+ public static class ComputeTestRunnable implements IgniteRunnable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor.
+ */
+ public ComputeTestRunnable() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public ComputeTestRunnable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal, float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void run() {
+ checkState();
+ }
+
+ /**
+ * Check the object state after serialization / deserialization
+ */
+ protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Test runnable, externalizable object. All fields are used only for serialization check.
+ */
+ public static class ComputeTestRunnableExternalizable extends ComputeTestRunnable implements Externalizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor (required by Externalizable).
+ */
+ public ComputeTestRunnableExternalizable() {
+ // No-op
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public ComputeTestRunnableExternalizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal, double dblVal, String strVal, Object[] arrVal,
+ TestJobEnum val) {
+ this.intVal = intVal;
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ JobUtils.writeJobState(out, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ isVal = in.readBoolean();
+ bVal = in.readByte();
+ cVal = in.readChar();
+ sVal = in.readShort();
+ intVal = in.readInt();
+ lVal = in.readLong();
+ fltVal = in.readFloat();
+ dblVal = in.readDouble();
+ strVal = (String)in.readObject();
+ arrVal = (Object[])in.readObject();
+ eVal = (TestJobEnum)in.readObject();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Test runnable, binarylizable object. All fields are used only for serialization check.
+ */
+ public static class ComputeTestRunnableBinarylizable extends ComputeTestRunnable implements Binarylizable {
+ /** */
+ private boolean isVal;
+
+ /** */
+ private byte bVal;
+
+ /** */
+ private char cVal;
+
+ /** */
+ private short sVal;
+
+ /** */
+ private int intVal;
+
+ /** */
+ private long lVal;
+
+ /** */
+ private float fltVal;
+
+ /** */
+ private double dblVal;
+
+ /** */
+ private String strVal;
+
+ /** */
+ private Object[] arrVal;
+
+ /** */
+ private TestJobEnum eVal;
+
+ /**
+ * Default constructor.
+ */
+ public ComputeTestRunnableBinarylizable() {
+ // No-op.
+ }
+
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param val Enum value.
+ */
+ public ComputeTestRunnableBinarylizable(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal, double dblVal, String strVal, Object[] arrVal,
+ TestJobEnum val) {
+ this.isVal = isVal;
+ this.bVal = bVal;
+ this.cVal = cVal;
+ this.sVal = sVal;
+ this.intVal = intVal;
+ this.lVal = lVal;
+ this.fltVal = fltVal;
+ this.dblVal = dblVal;
+ this.strVal = strVal;
+ this.arrVal = arrVal;
+ eVal = val;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+ JobUtils.writeJobState(writer, isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+ isVal = reader.readBoolean("isVal");
+ bVal = reader.readByte("bVal");
+ cVal = reader.readChar("cVal");
+ sVal = reader.readShort("sVal");
+ intVal = reader.readInt("intVal");
+ lVal = reader.readLong("lVal");
+ fltVal = reader.readFloat("fltVal");
+ dblVal = reader.readDouble("dblVal");
+ strVal = reader.readString("strVal");
+ arrVal = reader.readObjectArray("arrVal");
+ eVal = reader.readEnum("eVal");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void checkState() {
+ JobUtils.checkJobState(isVal, bVal, cVal, sVal, intVal, lVal, fltVal, dblVal, strVal, arrVal, eVal);
+ }
+ }
+
+ /**
+ * Creates test jobs with tested parameters
+ */
+ private static class JobFactory<T> implements Factory<T> {
+ /** */
+ private static final long serialVersionUID = 0;
+
+ /** */
+ private Class<?> cls;
+
+ /**
+ * @param cls Class.
+ */
+ JobFactory(Class<?> cls) {
+ this.cls = cls;
+ }
+
+ /** {@inheritDoc} */
+ @Override public T create() {
+ try {
+ Constructor<?> constructor = cls.getConstructor(Boolean.TYPE, Byte.TYPE, Character.TYPE,
+ Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, String.class, Object[].class, TestJobEnum.class);
+
+ return (T)constructor.newInstance(true,
+ Byte.MAX_VALUE,
+ Character.MAX_VALUE,
+ Short.MAX_VALUE,
+ Integer.MAX_VALUE,
+ Long.MAX_VALUE,
+ Float.MAX_VALUE,
+ Double.MAX_VALUE,
+ STR_VAL, ARRAY_VAL,
+ TestJobEnum.VALUE_2);
+ }
+ catch (NoSuchMethodException | InstantiationException | InvocationTargetException |
+ IllegalAccessException e) {
+ throw new IgniteException("Failed to create object using default constructor: " + cls, e);
+ }
+ }
+ }
+
+ /**
+ * Collection of utility methods to simplify EchoJob*, EchoCLosure*, EchoCallable* and ComputeTestRunnable* classes
+ */
+ private static class JobUtils {
+ /**
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param eVal Enum value.
+ */
+ private static void checkJobState(boolean isVal, byte bVal, char cVal, short sVal, int intVal, long lVal,
+ float fltVal,
+ double dblVal, String strVal, Object[] arrVal, TestJobEnum eVal) {
+ assertEquals(true, isVal);
+ assertEquals(Byte.MAX_VALUE, bVal);
+ assertEquals(Character.MAX_VALUE, cVal);
+ assertEquals(Short.MAX_VALUE, sVal);
+ assertEquals(Integer.MAX_VALUE, intVal);
+ assertEquals(Long.MAX_VALUE, lVal);
+ assertEquals(Float.MAX_VALUE, fltVal);
+ assertEquals(Double.MAX_VALUE, dblVal);
+ assertEquals(STR_VAL, strVal);
+ Assert.assertArrayEquals(ARRAY_VAL, arrVal);
+ assertEquals(TestJobEnum.VALUE_2, eVal);
+ }
+
+ /**
+ * @param writer Writer.
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param eVal Enum value.
+ * @throws BinaryObjectException If failed.
+ */
+ private static void writeJobState(BinaryWriter writer, boolean isVal, byte bVal, char cVal, short sVal,
+ int intVal, long lVal, float fltVal, double dblVal, String strVal,
+ Object[] arrVal, TestJobEnum eVal) throws BinaryObjectException {
+ writer.writeBoolean("isVal", isVal);
+ writer.writeByte("bVal", bVal);
+ writer.writeChar("cVal", cVal);
+ writer.writeShort("sVal", sVal);
+ writer.writeInt("intVal", intVal);
+ writer.writeLong("lVal", lVal);
+ writer.writeFloat("fltVal", fltVal);
+ writer.writeDouble("dblVal", dblVal);
+ writer.writeString("strVal", strVal);
+ writer.writeObjectArray("arrVal", arrVal);
+ writer.writeEnum("eVal", eVal);
+ }
+
+ /**
+ * @param out Out.
+ * @param isVal boolean value.
+ * @param bVal byte value.
+ * @param cVal char value.
+ * @param sVal short value.
+ * @param intVal int value.
+ * @param lVal long value.
+ * @param fltVal float value.
+ * @param dblVal double value.
+ * @param strVal String value.
+ * @param arrVal Array value.
+ * @param eVal Enum value.
+ * @throws IOException If failed.
+ */
+ private static void writeJobState(ObjectOutput out, boolean isVal, byte bVal, char cVal, short sVal,
+ int intVal, long lVal, float fltVal, double dblVal, String strVal, Object[] arrVal,
+ TestJobEnum eVal) throws IOException {
+ out.writeBoolean(isVal);
+ out.writeByte(bVal);
+ out.writeChar(cVal);
+ out.writeShort(sVal);
+ out.writeInt(intVal);
+ out.writeLong(lVal);
+ out.writeFloat(fltVal);
+ out.writeDouble(dblVal);
+ out.writeObject(strVal);
+ out.writeObject(arrVal);
+ out.writeObject(eVal);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6de16db/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
index e5856f0..0be6d50 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
@@ -215,7 +215,7 @@ public class ConfigVariations {
/**
* @return Marshaller.
*/
- private static Factory<OptimizedMarshaller> optimizedMarshallerFactory() {
+ public static Factory<OptimizedMarshaller> optimizedMarshallerFactory() {
return new Factory<OptimizedMarshaller>() {
@Override public OptimizedMarshaller create() {
OptimizedMarshaller marsh = new OptimizedMarshaller(true);
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6de16db/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java
index b22f289..258eba8 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java
@@ -21,13 +21,16 @@ import java.io.Externalizable;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInput;
+import java.io.ObjectInputStream;
import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import org.apache.commons.io.FileUtils;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.marshaller.jdk.JdkMarshaller;
import org.apache.ignite.testframework.configvariations.VariationsTestsConfig;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
@@ -197,6 +200,12 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr
for (int i = 0; i < DataMode.values().length; i++) {
dataMode = DataMode.values()[i];
+ if ((getConfiguration().getMarshaller() instanceof JdkMarshaller)
+ && (dataMode == DataMode.PLANE_OBJECT)) {
+ info("Skip test for JdkMarshaller & PLANE_OBJECT data mode");
+ continue;
+ }
+
info("Running test in data mode: " + dataMode);
if (i != 0)
@@ -289,6 +298,13 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr
protected TestEnum enumVal;
/**
+ * Default constructor must be accessible for deserialize subclasses by JDK serialization API.
+ */
+ TestObject() {
+ // No-op.
+ }
+
+ /**
* @param val Value.
*/
TestObject(int val) {
@@ -345,6 +361,31 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr
public SerializableObject(int val) {
super(val);
}
+
+ /**
+ * Custom serialization of superclass because {@link TestObject} is non-serializable.
+ *
+ * @param out output stream.
+ * @throws IOException if de-serialization failed.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.writeInt(val);
+ out.writeObject(strVal);
+ out.writeObject(enumVal);
+ }
+
+ /**
+ * Custom deserialization of superclass because {@link TestObject} is non-serializable.
+ *
+ * @param in input stream
+ * @throws IOException if de-serialization failed.
+ * @throws ClassNotFoundException if de-serialization failed.
+ */
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ val = in.readInt();
+ strVal = (String)in.readObject();
+ enumVal = (TestEnum)in.readObject();
+ }
}
/**
@@ -354,7 +395,7 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr
/**
* Default constructor.
*/
- ExternalizableObject() {
+ public ExternalizableObject() {
super(-1);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6de16db/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeBasicConfigVariationsFullApiTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeBasicConfigVariationsFullApiTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeBasicConfigVariationsFullApiTestSuite.java
new file mode 100644
index 0000000..1be932a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeBasicConfigVariationsFullApiTestSuite.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.testsuites;
+
+import junit.framework.TestSuite;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.processors.compute.IgniteComputeConfigVariationsFullApiTest;
+import org.apache.ignite.marshaller.jdk.JdkMarshaller;
+import org.apache.ignite.testframework.configvariations.ConfigParameter;
+import org.apache.ignite.testframework.configvariations.ConfigVariations;
+import org.apache.ignite.testframework.configvariations.ConfigVariationsTestSuiteBuilder;
+import org.apache.ignite.testframework.configvariations.Parameters;
+
+/**
+ * Full API compute test.
+ */
+public class IgniteComputeBasicConfigVariationsFullApiTestSuite extends TestSuite {
+ /** */
+ @SuppressWarnings("unchecked")
+ private static final ConfigParameter<IgniteConfiguration>[][] BASIC_COMPUTE_SET = new ConfigParameter[][] {
+ Parameters.objectParameters("setMarshaller",
+ Parameters.factory(JdkMarshaller.class),
+ Parameters.factory(BinaryMarshaller.class),
+ ConfigVariations.optimizedMarshallerFactory()
+ ),
+ Parameters.booleanParameters("setPeerClassLoadingEnabled"),
+ Parameters.booleanParameters("setMarshalLocalJobs"),
+ };
+
+ /**
+ * @return Compute API test suite.
+ * @throws Exception If failed.
+ */
+ public static TestSuite suite() throws Exception {
+ TestSuite suite = new TestSuite("Compute New Full API Test Suite");
+
+ suite.addTest(new ConfigVariationsTestSuiteBuilder(
+ "Single server",
+ IgniteComputeConfigVariationsFullApiTest.class)
+ .igniteParams(BASIC_COMPUTE_SET)
+ .gridsCount(1)
+ .build());
+
+ // Tests run on server (node#0) & client(node#1).
+ suite.addTest(new ConfigVariationsTestSuiteBuilder(
+ "3 servers, 1 client",
+ IgniteComputeConfigVariationsFullApiTest.class)
+ .igniteParams(BASIC_COMPUTE_SET)
+ .gridsCount(4)
+ .testedNodesCount(2)
+ .withClients()
+ .build());
+
+ return suite;
+ }
+}
[7/7] ignite git commit: Merge branch 'master' into ignite-2523-1
Posted by vo...@apache.org.
Merge branch 'master' into ignite-2523-1
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/be738808
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/be738808
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/be738808
Branch: refs/heads/ignite-2523-1
Commit: be738808d14b6dbeea6c65a0a34387cbf13bef10
Parents: 2566e0b 2ff64c2
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Sat Apr 23 11:46:46 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Sat Apr 23 11:46:46 2016 +0300
----------------------------------------------------------------------
.../CacheContinuousAsyncQueryExample.java | 138 ++
.../datagrid/CacheContinuousQueryExample.java | 13 +-
.../ignite/cache/query/ContinuousQuery.java | 27 +
.../configuration/IgniteConfiguration.java | 32 +
.../ignite/internal/GridKernalContext.java | 8 +
.../ignite/internal/GridKernalContextImpl.java | 12 +
.../apache/ignite/internal/IgniteKernal.java | 3 +
.../org/apache/ignite/internal/IgnitionEx.java | 16 +-
.../processors/cache/GridCacheEntryEx.java | 5 +-
.../processors/cache/GridCacheMapEntry.java | 49 +-
.../dht/atomic/GridDhtAtomicCache.java | 98 +-
.../dht/atomic/GridDhtAtomicUpdateFuture.java | 121 +-
.../dht/atomic/GridDhtAtomicUpdateRequest.java | 33 +-
.../distributed/near/GridNearAtomicCache.java | 3 +-
.../continuous/CacheContinuousQueryEvent.java | 7 +
.../continuous/CacheContinuousQueryHandler.java | 446 +++-
.../CacheContinuousQueryListener.java | 6 +-
.../continuous/CacheContinuousQueryManager.java | 62 +-
.../apache/ignite/lang/IgniteAsyncCallback.java | 111 +
.../thread/IgniteStripedThreadPoolExecutor.java | 164 +-
.../processors/cache/GridCacheTestEntryEx.java | 4 +-
...FailoverAtomicPrimaryWriteOrderSelfTest.java | 50 +
...sQueryAsyncFailoverTxReplicatedSelfTest.java | 37 +
...eContinuousQueryAsyncFailoverTxSelfTest.java | 44 +
...eContinuousQueryAsyncFilterListenerTest.java | 986 +++++++++
...ryFactoryAsyncFilterRandomOperationTest.java | 131 ++
...usQueryFactoryFilterRandomOperationTest.java | 725 +++++++
.../CacheContinuousQueryFactoryFilterTest.java | 714 -------
...ContinuousQueryFailoverAbstractSelfTest.java | 63 +-
.../CacheContinuousQueryLostPartitionTest.java | 14 +
...ontinuousQueryOperationFromCallbackTest.java | 627 ++++++
.../CacheContinuousQueryOrderingEventTest.java | 722 +++++++
...acheContinuousQueryRandomOperationsTest.java | 23 +
...gniteComputeConfigVariationsFullApiTest.java | 2009 ++++++++++++++++++
.../configvariations/ConfigVariations.java | 2 +-
.../junits/GridTestKernalContext.java | 1 +
.../IgniteConfigVariationsAbstractTest.java | 43 +-
...teBasicConfigVariationsFullApiTestSuite.java | 72 +
.../IgniteBinaryCacheQueryTestSuite.java | 1 -
.../IgniteCacheQuerySelfTestSuite3.java | 14 +-
.../IgniteCacheQuerySelfTestSuite4.java | 7 +
.../ignite/schema/generator/CodeGenerator.java | 26 +-
.../ignite/schema/generator/XmlGenerator.java | 45 +-
.../schema/parser/DatabaseMetadataParser.java | 6 +-
.../ignite/schema/ui/SchemaImportApp.java | 30 +-
.../schema/test/AbstractSchemaImportTest.java | 10 +-
.../schema/test/generator/XmlGeneratorTest.java | 4 +-
.../apache/ignite/schema/test/model/Objects.txt | 31 +-
.../ignite/schema/test/model/Primitives.txt | 31 +-
.../org/apache/ignite/schema/test/model/Tst.txt | 31 +-
.../schema/test/model/ignite-type-metadata.xml | 42 +
.../test/parser/DbMetadataParserTest.java | 2 +-
.../cache/CacheEntryEventAsyncProbe.java | 61 +
.../yardstick/cache/CacheEntryEventProbe.java | 33 +-
54 files changed, 6764 insertions(+), 1231 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/be738808/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/be738808/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/be738808/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
----------------------------------------------------------------------
[3/7] ignite git commit: IGNITE-2004 Fixed "Asynchronous execution of
ContinuousQuery's remote filter & local list".
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOrderingEventTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOrderingEventTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOrderingEventTest.java
new file mode 100644
index 0000000..7d975f2
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOrderingEventTest.java
@@ -0,0 +1,722 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.configuration.FactoryBuilder;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.cache.CacheEntryProcessor;
+import org.apache.ignite.cache.CacheMemoryMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.PA;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteAsyncCallback;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_VALUES;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.PRIMARY_SYNC;
+
+/**
+ *
+ */
+public class CacheContinuousQueryOrderingEventTest extends GridCommonAbstractTest {
+ /** */
+ public static final int LISTENER_CNT = 3;
+
+ /** */
+ public static final int KEYS = 10;
+
+ /** */
+ private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final int NODES = 5;
+
+ /** */
+ public static final int ITERATION_CNT = 100;
+
+ /** */
+ private boolean client;
+
+ /** */
+ private static volatile boolean fail;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+ ((TcpCommunicationSpi)cfg.getCommunicationSpi()).setSharedMemoryPort(-1);
+
+ cfg.setClientMode(client);
+
+ MemoryEventStorageSpi storeSpi = new MemoryEventStorageSpi();
+ storeSpi.setExpireCount(100);
+
+ cfg.setEventStorageSpi(storeSpi);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(NODES - 1);
+
+ client = true;
+
+ startGrid(NODES - 1);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ super.beforeTest();
+
+ fail = false;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOnheapTwoBackup() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ ONHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOffheapTwoBackup() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ OFFHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOffheapValuesTwoBackup() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ OFFHEAP_VALUES, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicReplicatedOffheap() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED, 0, ATOMIC,
+ OFFHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxOnheapTwoBackup() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL,
+ ONHEAP_TIERED, FULL_SYNC);
+
+ doOrderingTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxOnheapWithoutBackup() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 0, TRANSACTIONAL,
+ ONHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxOnheapWithoutBackupFullSync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 0, TRANSACTIONAL,
+ ONHEAP_TIERED, FULL_SYNC);
+
+ doOrderingTest(ccfg, false);
+ }
+
+ // ASYNC
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOnheapTwoBackupAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ ONHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOnheapTwoBackupAsyncFullSync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ ONHEAP_TIERED, FULL_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOffheapTwoBackupAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ OFFHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOffheapTwoBackupAsyncFullSync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ OFFHEAP_TIERED, FULL_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOffheapValuesTwoBackupAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ OFFHEAP_VALUES, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOffheapValuesTwoBackupAsyncFullSync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC,
+ OFFHEAP_VALUES, FULL_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicReplicatedAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED, 0, ATOMIC,
+ ONHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicReplicatedAsyncFullSync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED, 0, ATOMIC,
+ ONHEAP_TIERED, FULL_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicReplicatedOffheapAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED, 0, ATOMIC,
+ OFFHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicOnheapWithoutBackupAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 0, ATOMIC,
+ ONHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxOnheapTwoBackupAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL,
+ ONHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxOnheapAsync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 0, TRANSACTIONAL,
+ ONHEAP_TIERED, PRIMARY_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxOnheapAsyncFullSync() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 0, TRANSACTIONAL,
+ ONHEAP_TIERED, FULL_SYNC);
+
+ doOrderingTest(ccfg, true);
+ }
+
+ /**
+ * @param ccfg Cache configuration.
+ * @param async Async filter.
+ * @throws Exception If failed.
+ */
+ protected void doOrderingTest(
+ final CacheConfiguration ccfg,
+ final boolean async)
+ throws Exception {
+ ignite(0).createCache(ccfg);
+
+ List<QueryCursor<?>> qries = new ArrayList<>();
+
+ try {
+ List<BlockingQueue<CacheEntryEvent<QueryTestKey, QueryTestValue>>> rcvdEvts =
+ new ArrayList<>(LISTENER_CNT * NODES);
+
+ final AtomicInteger qryCntr = new AtomicInteger(0);
+
+ final int threadCnt = 20;
+
+ for (int idx = 0; idx < NODES; idx++) {
+ for (int i = 0; i < LISTENER_CNT; i++) {
+ BlockingQueue<CacheEntryEvent<QueryTestKey, QueryTestValue>> queue =
+ new ArrayBlockingQueue<>(ITERATION_CNT * threadCnt);
+
+ ContinuousQuery qry = new ContinuousQuery();
+
+ if (async) {
+ qry.setLocalListener(new TestCacheAsyncEventListener(queue, qryCntr));
+
+ qry.setRemoteFilterFactory(FactoryBuilder.factoryOf(
+ new CacheTestRemoteFilterAsync(ccfg.getName())));
+ }
+ else {
+ qry.setLocalListener(new TestCacheEventListener(queue, qryCntr));
+
+ qry.setRemoteFilterFactory(FactoryBuilder.factoryOf(
+ new CacheTestRemoteFilter(ccfg.getName())));
+ }
+
+ rcvdEvts.add(queue);
+
+ IgniteCache<Object, Object> cache = grid(idx).cache(ccfg.getName());
+
+ QueryCursor qryCursor = cache.query(qry);
+
+ qries.add(qryCursor);
+ }
+ }
+
+ IgniteInternalFuture<Long> f = GridTestUtils.runMultiThreadedAsync(new Runnable() {
+ @Override public void run() {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ for (int i = 0; i < ITERATION_CNT; i++) {
+ IgniteCache<QueryTestKey, QueryTestValue> cache =
+ grid(rnd.nextInt(NODES)).cache(ccfg.getName());
+
+ QueryTestKey key = new QueryTestKey(rnd.nextInt(KEYS));
+
+ boolean startTx = cache.getConfiguration(CacheConfiguration.class).getAtomicityMode() ==
+ TRANSACTIONAL && rnd.nextBoolean();
+
+ Transaction tx = null;
+
+ if (startTx)
+ tx = cache.unwrap(Ignite.class).transactions().txStart();
+
+ try {
+ if ((cache.get(key) == null) || rnd.nextBoolean()) {
+ cache.invoke(key, new CacheEntryProcessor<QueryTestKey, QueryTestValue, Object>() {
+ @Override public Object process(
+ MutableEntry<QueryTestKey, QueryTestValue> entry,
+ Object... arguments)
+ throws EntryProcessorException {
+ if (entry.exists())
+ entry.setValue(new QueryTestValue(entry.getValue().val1 + 1));
+ else
+ entry.setValue(new QueryTestValue(0));
+
+ return null;
+ }
+ });
+ }
+ else {
+ QueryTestValue val;
+ QueryTestValue newVal;
+
+ do {
+ val = cache.get(key);
+
+ newVal = val == null ?
+ new QueryTestValue(0) : new QueryTestValue(val.val1 + 1);
+ }
+ while (!cache.replace(key, val, newVal));
+ }
+ }
+ finally {
+ if (tx != null)
+ tx.commit();
+ }
+ }
+ }
+ }, threadCnt, "put-thread");
+
+ f.get(15, TimeUnit.SECONDS);
+
+ GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return qryCntr.get() >= ITERATION_CNT * threadCnt * LISTENER_CNT * NODES;
+ }
+ }, 1000L);
+
+ for (BlockingQueue<CacheEntryEvent<QueryTestKey, QueryTestValue>> queue : rcvdEvts)
+ checkEvents(queue, ITERATION_CNT * threadCnt);
+
+ assertFalse("Ordering invocations of filter broken.", fail);
+ }
+ finally {
+ for (QueryCursor<?> qry : qries)
+ qry.close();
+
+ ignite(0).destroyCache(ccfg.getName());
+ }
+ }
+
+ /**
+ * @param queue Event queue.
+ * @throws Exception If failed.
+ */
+ private void checkEvents(BlockingQueue<CacheEntryEvent<QueryTestKey, QueryTestValue>> queue, int expCnt)
+ throws Exception {
+ CacheEntryEvent<QueryTestKey, QueryTestValue> evt;
+ int cnt = 0;
+ Map<QueryTestKey, Integer> vals = new HashMap<>();
+
+ while ((evt = queue.poll(100, TimeUnit.MILLISECONDS)) != null) {
+ assertNotNull(evt);
+ assertNotNull(evt.getKey());
+
+ Integer preVal = vals.get(evt.getKey());
+
+ if (preVal == null)
+ assertEquals(new QueryTestValue(0), evt.getValue());
+ else {
+ if (!new QueryTestValue(preVal + 1).equals(evt.getValue()))
+ assertEquals("Key event: " + evt.getKey(), new QueryTestValue(preVal + 1), evt.getValue());
+ }
+
+ vals.put(evt.getKey(), evt.getValue().val1);
+
+ ++cnt;
+ }
+
+ assertEquals(expCnt, cnt);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long getTestTimeout() {
+ return TimeUnit.MINUTES.toMillis(8);
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ private static class CacheTestRemoteFilterAsync extends CacheTestRemoteFilter {
+ /**
+ * @param cacheName Cache name.
+ */
+ public CacheTestRemoteFilterAsync(String cacheName) {
+ super(cacheName);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class CacheTestRemoteFilter implements
+ CacheEntryEventSerializableFilter<QueryTestKey, QueryTestValue> {
+ /** */
+ private Map<QueryTestKey, QueryTestValue> prevVals = new ConcurrentHashMap<>();
+
+ /** */
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** */
+ private String cacheName;
+
+ /**
+ * @param cacheName Cache name.
+ */
+ public CacheTestRemoteFilter(String cacheName) {
+ this.cacheName = cacheName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> e) {
+ if (affinity(ignite.cache(cacheName)).isPrimary(ignite.cluster().localNode(), e.getKey())) {
+ QueryTestValue prevVal = prevVals.put(e.getKey(), e.getValue());
+
+ if (prevVal != null) {
+ if (!new QueryTestValue(prevVal.val1 + 1).equals(e.getValue()))
+ fail = true;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ private static class TestCacheAsyncEventListener extends TestCacheEventListener {
+ /**
+ * @param queue Queue.
+ * @param cntr Received events counter.
+ */
+ public TestCacheAsyncEventListener(BlockingQueue<CacheEntryEvent<QueryTestKey, QueryTestValue>> queue,
+ AtomicInteger cntr) {
+ super(queue, cntr);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class TestCacheEventListener implements CacheEntryUpdatedListener<QueryTestKey, QueryTestValue> {
+ /** */
+ private final BlockingQueue<CacheEntryEvent<QueryTestKey, QueryTestValue>> queue;
+
+ /** */
+ private final AtomicInteger cntr;
+
+ /**
+ * @param queue Queue.
+ * @param cntr Received events counter.
+ */
+ public TestCacheEventListener(BlockingQueue<CacheEntryEvent<QueryTestKey, QueryTestValue>> queue,
+ AtomicInteger cntr) {
+ this.queue = queue;
+ this.cntr = cntr;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts) {
+ for (CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> e : evts) {
+ queue.add((CacheEntryEvent<QueryTestKey, QueryTestValue>)e);
+
+ cntr.incrementAndGet();
+ }
+ }
+ }
+
+ /**
+ * @param cacheMode Cache mode.
+ * @param backups Number of backups.
+ * @param atomicityMode Cache atomicity mode.
+ * @param memoryMode Cache memory mode.
+ * @param writeMode Cache write mode.
+ * @return Cache configuration.
+ */
+ protected CacheConfiguration<Object, Object> cacheConfiguration(
+ CacheMode cacheMode,
+ int backups,
+ CacheAtomicityMode atomicityMode,
+ CacheMemoryMode memoryMode,
+ CacheWriteSynchronizationMode writeMode) {
+ CacheConfiguration<Object, Object> ccfg = new CacheConfiguration<>();
+
+ ccfg.setName("test-cache-" + atomicityMode + "-" + cacheMode + "-" + memoryMode + "-" + memoryMode + "-"
+ + backups);
+ ccfg.setAtomicityMode(atomicityMode);
+ ccfg.setCacheMode(cacheMode);
+ ccfg.setMemoryMode(memoryMode);
+ ccfg.setWriteSynchronizationMode(writeMode);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+
+ if (cacheMode == PARTITIONED)
+ ccfg.setBackups(backups);
+
+ return ccfg;
+ }
+
+ /**
+ *
+ */
+ public static class QueryTestKey implements Serializable, Comparable {
+ /** */
+ private final Integer key;
+
+ /**
+ * @param key Key.
+ */
+ public QueryTestKey(Integer key) {
+ this.key = key;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ QueryTestKey that = (QueryTestKey)o;
+
+ return key.equals(that.key);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return key.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(QueryTestKey.class, this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compareTo(Object o) {
+ return key - ((QueryTestKey)o).key;
+ }
+ }
+
+ /**
+ *
+ */
+ public static class QueryTestValue implements Serializable {
+ /** */
+ @GridToStringInclude
+ protected final Integer val1;
+
+ /** */
+ @GridToStringInclude
+ protected final String val2;
+
+ /**
+ * @param val Value.
+ */
+ public QueryTestValue(Integer val) {
+ this.val1 = val;
+ this.val2 = String.valueOf(val);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ QueryTestValue that = (QueryTestValue) o;
+
+ return val1.equals(that.val1) && val2.equals(that.val2);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = val1.hashCode();
+
+ res = 31 * res + val2.hashCode();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(QueryTestValue.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryRandomOperationsTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryRandomOperationsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryRandomOperationsTest.java
index e9fbf70..a6c33bb 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryRandomOperationsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryRandomOperationsTest.java
@@ -62,6 +62,7 @@ import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.PA;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
@@ -118,6 +119,7 @@ public class CacheContinuousQueryRandomOperationsTest extends GridCommonAbstract
IgniteConfiguration cfg = super.getConfiguration(gridName);
((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+ ((TcpCommunicationSpi)cfg.getCommunicationSpi()).setSharedMemoryPort(-1);
cfg.setClientMode(client);
@@ -598,6 +600,9 @@ public class CacheContinuousQueryRandomOperationsTest extends GridCommonAbstract
final List<CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> evts =
new CopyOnWriteArrayList<>();
+ if (noOpFilterFactory() != null)
+ qry.setRemoteFilterFactory(noOpFilterFactory());
+
qry.setLocalListener(new CacheEntryUpdatedListener<QueryTestKey, QueryTestValue>() {
@Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
? extends QueryTestValue>> events) throws CacheEntryListenerException {
@@ -684,9 +689,17 @@ public class CacheContinuousQueryRandomOperationsTest extends GridCommonAbstract
checkSingleEvent(evts.get(7), CREATED, new QueryTestValue(5), null);
checkSingleEvent(evts.get(8), EventType.UPDATED, new QueryTestValue(6), new QueryTestValue(5));
+ evts.clear();
+
cache.remove(key);
cache.remove(key);
+ assert GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return evts.size() == 1;
+ }
+ }, 5_000);
+
evts.clear();
log.info("Finish iteration: " + i);
@@ -699,6 +712,13 @@ public class CacheContinuousQueryRandomOperationsTest extends GridCommonAbstract
}
/**
+ * @return No-op filter factory for batch operations.
+ */
+ protected Factory<? extends CacheEntryEventFilter<QueryTestKey, QueryTestValue>> noOpFilterFactory() {
+ return null;
+ }
+
+ /**
* @param ccfg Cache configuration.
* @throws Exception If failed.
*/
@@ -711,6 +731,9 @@ public class CacheContinuousQueryRandomOperationsTest extends GridCommonAbstract
final List<CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> evts =
new CopyOnWriteArrayList<>();
+ if (noOpFilterFactory() != null)
+ qry.setRemoteFilterFactory(noOpFilterFactory());
+
qry.setLocalListener(new CacheEntryUpdatedListener<QueryTestKey, QueryTestValue>() {
@Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
? extends QueryTestValue>> events) throws CacheEntryListenerException {
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridTestKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridTestKernalContext.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridTestKernalContext.java
index b4c31be..e4afe73 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridTestKernalContext.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridTestKernalContext.java
@@ -60,6 +60,7 @@ public class GridTestKernalContext extends GridKernalContextImpl {
null,
null,
null,
+ null,
U.allPluginProviders());
GridTestUtils.setFieldValue(grid(), "cfg", config());
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
index 30625fe..761d4bd 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
@@ -44,7 +44,6 @@ public class IgniteBinaryCacheQueryTestSuite extends TestSuite {
suite.addTestSuite(BinarySerializationQuerySelfTest.class);
suite.addTestSuite(BinarySerializationQueryWithReflectiveSerializerSelfTest.class);
suite.addTestSuite(IgniteCacheBinaryObjectsScanSelfTest.class);
- suite.addTestSuite(CacheContinuousQueryLostPartitionTest.class);
//Should be adjusted. Not ready to be used with BinaryMarshaller.
//suite.addTestSuite(GridCacheBinarySwapScanQuerySelfTest.class);
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
index fbb3091..e0e81b7 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
@@ -20,9 +20,14 @@ package org.apache.ignite.testsuites;
import junit.framework.TestSuite;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousBatchAckTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousBatchForceServerModeAckTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryAsyncFilterListenerTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryExecuteInPrimaryTest;
-import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFactoryFilterTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFactoryAsyncFilterRandomOperationTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFactoryFilterRandomOperationTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryLostPartitionTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryOperationFromCallbackTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryOperationP2PTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryOrderingEventTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryRandomOperationsTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryRandomOperationsTwoNodesTest;
import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryAtomicNearEnabledSelfTest;
@@ -87,12 +92,17 @@ public class IgniteCacheQuerySelfTestSuite3 extends TestSuite {
suite.addTestSuite(IgniteCacheContinuousQueryClientTxReconnectTest.class);
suite.addTestSuite(CacheContinuousQueryRandomOperationsTest.class);
suite.addTestSuite(CacheContinuousQueryRandomOperationsTwoNodesTest.class);
- suite.addTestSuite(CacheContinuousQueryFactoryFilterTest.class);
suite.addTestSuite(GridCacheContinuousQueryConcurrentTest.class);
+ suite.addTestSuite(CacheContinuousQueryAsyncFilterListenerTest.class);
+ suite.addTestSuite(CacheContinuousQueryFactoryFilterRandomOperationTest.class);
+ suite.addTestSuite(CacheContinuousQueryFactoryAsyncFilterRandomOperationTest.class);
+ suite.addTestSuite(CacheContinuousQueryOrderingEventTest.class);
+ suite.addTestSuite(CacheContinuousQueryOperationFromCallbackTest.class);
suite.addTestSuite(CacheContinuousQueryOperationP2PTest.class);
suite.addTestSuite(CacheContinuousBatchAckTest.class);
suite.addTestSuite(CacheContinuousBatchForceServerModeAckTest.class);
suite.addTestSuite(CacheContinuousQueryExecuteInPrimaryTest.class);
+ suite.addTestSuite(CacheContinuousQueryLostPartitionTest.class);
return suite;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite4.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite4.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite4.java
index fa4e642..c4fcdac 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite4.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite4.java
@@ -18,6 +18,9 @@
package org.apache.ignite.testsuites;
import junit.framework.TestSuite;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryAsyncFailoverAtomicPrimaryWriteOrderSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryAsyncFailoverTxReplicatedSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryAsyncFailoverTxSelfTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFailoverAtomicPrimaryWriteOrderOffheapTieredTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest;
import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFailoverAtomicReplicatedSelfTest;
@@ -44,6 +47,10 @@ public class IgniteCacheQuerySelfTestSuite4 extends TestSuite {
suite.addTestSuite(CacheContinuousQueryFailoverAtomicPrimaryWriteOrderOffheapTieredTest.class);
suite.addTestSuite(CacheContinuousQueryFailoverTxOffheapTieredTest.class);
+ suite.addTestSuite(CacheContinuousQueryAsyncFailoverAtomicPrimaryWriteOrderSelfTest.class);
+ suite.addTestSuite(CacheContinuousQueryAsyncFailoverTxReplicatedSelfTest.class);
+ suite.addTestSuite(CacheContinuousQueryAsyncFailoverTxSelfTest.class);
+
return suite;
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventAsyncProbe.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventAsyncProbe.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventAsyncProbe.java
new file mode 100644
index 0000000..0ea66d4
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventAsyncProbe.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.yardstick.cache;
+
+import java.util.concurrent.atomic.AtomicLong;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.lang.IgniteAsyncCallback;
+
+/**
+ * Probe which calculate continuous query events.
+ */
+public class CacheEntryEventAsyncProbe extends CacheEntryEventProbe {
+ /** */
+ @Override protected CacheEntryUpdatedListener<Integer, Integer> localListener(AtomicLong cntr) {
+ return new CacheEntryEventListener(cntr);
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ private static final class CacheEntryEventListener implements CacheEntryUpdatedListener<Integer, Integer> {
+ /** */
+ private AtomicLong cnt;
+
+ /**
+ * @param cnt Counter.
+ */
+ public CacheEntryEventListener(AtomicLong cnt) {
+ this.cnt = cnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>> events)
+ throws CacheEntryListenerException {
+ int size = 0;
+
+ for (CacheEntryEvent<? extends Integer, ? extends Integer> e : events)
+ ++size;
+
+ cnt.addAndGet(size);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java
index e42479a..a25f975 100644
--- a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java
@@ -45,9 +45,6 @@ public class CacheEntryEventProbe implements BenchmarkProbe {
/** */
private BenchmarkConfiguration cfg;
- /** Counter. */
- private AtomicLong cnt = new AtomicLong(0);
-
/** Collected points. */
private Collection<BenchmarkProbePoint> collected = new ArrayList<>();
@@ -67,17 +64,9 @@ public class CacheEntryEventProbe implements BenchmarkProbe {
if (drv0.cache() != null) {
ContinuousQuery<Integer, Integer> qry = new ContinuousQuery<>();
- qry.setLocalListener(new CacheEntryUpdatedListener<Integer, Integer>() {
- @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>>
- events) throws CacheEntryListenerException {
- int size = 0;
-
- for (CacheEntryEvent<? extends Integer, ? extends Integer> e : events)
- ++size;
+ final AtomicLong cnt = new AtomicLong();
- cnt.addAndGet(size);
- }
- });
+ qry.setLocalListener(localListener(cnt));
qryCur = drv0.cache().query(qry);
@@ -113,6 +102,24 @@ public class CacheEntryEventProbe implements BenchmarkProbe {
+ " probe. Probably, the driver doesn't provide \"cache()\" method.");
}
+ /**
+ * @param cntr Received event counter.
+ * @return Local listener.
+ */
+ protected CacheEntryUpdatedListener<Integer, Integer> localListener(final AtomicLong cntr) {
+ return new CacheEntryUpdatedListener<Integer, Integer>() {
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>> events)
+ throws CacheEntryListenerException {
+ int size = 0;
+
+ for (CacheEntryEvent<? extends Integer, ? extends Integer> e : events)
+ ++size;
+
+ cntr.addAndGet(size);
+ }
+ };
+ }
+
/** {@inheritDoc} */
@Override public void stop() throws Exception {
if (qryCur != null) {
[4/7] ignite git commit: IGNITE-2004 Fixed "Asynchronous execution of
ContinuousQuery's remote filter & local list".
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterRandomOperationTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterRandomOperationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterRandomOperationTest.java
new file mode 100644
index 0000000..dbaafe1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterRandomOperationTest.java
@@ -0,0 +1,725 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadLocalRandom;
+import javax.cache.configuration.CacheEntryListenerConfiguration;
+import javax.cache.configuration.Factory;
+import javax.cache.configuration.FactoryBuilder;
+import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
+import javax.cache.event.CacheEntryCreatedListener;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryEventFilter;
+import javax.cache.event.CacheEntryExpiredListener;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryRemovedListener;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.CacheQueryEntryEvent;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.transactions.Transaction;
+import org.apache.ignite.transactions.TransactionConcurrency;
+import org.apache.ignite.transactions.TransactionIsolation;
+import org.jetbrains.annotations.NotNull;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFactoryFilterRandomOperationTest.NonSerializableFilter.isAccepted;
+import static org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryRandomOperationsTest.ContinuousDeploy.CLIENT;
+import static org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryRandomOperationsTest.ContinuousDeploy.SERVER;
+import static org.apache.ignite.transactions.TransactionIsolation.READ_COMMITTED;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+import static org.apache.ignite.transactions.TransactionIsolation.SERIALIZABLE;
+
+/**
+ *
+ */
+public class CacheContinuousQueryFactoryFilterRandomOperationTest extends CacheContinuousQueryRandomOperationsTest {
+ /** */
+ private static final int NODES = 5;
+
+ /** */
+ private static final int KEYS = 50;
+
+ /** */
+ private static final int VALS = 10;
+
+ /** */
+ public static final int ITERATION_CNT = 40;
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testInternalQuery() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED,
+ 1,
+ ATOMIC,
+ ONHEAP_TIERED,
+ false);
+
+ final IgniteCache<Object, Object> cache = grid(0).createCache(ccfg);
+
+ UUID uuid = null;
+
+ try {
+ for (int i = 0; i < 10; i++)
+ cache.put(i, i);
+
+ final CountDownLatch latch = new CountDownLatch(5);
+
+ CacheEntryUpdatedListener lsnr = new CacheEntryUpdatedListener() {
+ @Override public void onUpdated(Iterable iterable) throws CacheEntryListenerException {
+ for (Object evt : iterable) {
+ latch.countDown();
+
+ log.info("Received event: " + evt);
+ }
+ }
+ };
+
+ uuid = grid(0).context().cache().cache(cache.getName()).context().continuousQueries()
+ .executeInternalQuery(lsnr, new SerializableFilter(), false, true, true);
+
+ for (int i = 10; i < 20; i++)
+ cache.put(i, i);
+
+ assertTrue(latch.await(3, SECONDS));
+ }
+ finally {
+ if (uuid != null)
+ grid(0).context().cache().cache(cache.getName()).context().continuousQueries()
+ .cancelInternalQuery(uuid);
+
+ grid(0).destroyCache(ccfg.getName());
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void doTestContinuousQuery(CacheConfiguration<Object, Object> ccfg, ContinuousDeploy deploy)
+ throws Exception {
+ ignite(0).createCache(ccfg);
+
+ try {
+ long seed = System.currentTimeMillis();
+
+ Random rnd = new Random(seed);
+
+ log.info("Random seed: " + seed);
+
+ List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues = new ArrayList<>();
+
+ Collection<QueryCursor<?>> curs = new ArrayList<>();
+
+ Collection<T2<Integer, MutableCacheEntryListenerConfiguration>> lsnrCfgs = new ArrayList<>();
+
+ if (deploy == CLIENT)
+ evtsQueues.add(registerListener(ccfg.getName(), NODES - 1, curs, lsnrCfgs, rnd.nextBoolean()));
+ else if (deploy == SERVER)
+ evtsQueues.add(registerListener(ccfg.getName(), rnd.nextInt(NODES - 1), curs, lsnrCfgs,
+ rnd.nextBoolean()));
+ else {
+ boolean isSync = rnd.nextBoolean();
+
+ for (int i = 0; i < NODES - 1; i++)
+ evtsQueues.add(registerListener(ccfg.getName(), i, curs, lsnrCfgs, isSync));
+ }
+
+ ConcurrentMap<Object, Object> expData = new ConcurrentHashMap<>();
+
+ Map<Integer, Long> partCntr = new ConcurrentHashMap<>();
+
+ try {
+ for (int i = 0; i < ITERATION_CNT; i++) {
+ if (i % 10 == 0)
+ log.info("Iteration: " + i);
+
+ for (int idx = 0; idx < NODES; idx++)
+ randomUpdate(rnd, evtsQueues, expData, partCntr, grid(idx).cache(ccfg.getName()));
+ }
+ }
+ finally {
+ for (QueryCursor<?> cur : curs)
+ cur.close();
+
+ for (T2<Integer, MutableCacheEntryListenerConfiguration> e : lsnrCfgs)
+ grid(e.get1()).cache(ccfg.getName()).deregisterCacheEntryListener(e.get2());
+ }
+ }
+ finally {
+ ignite(0).destroyCache(ccfg.getName());
+ }
+ }
+
+ /**
+ * @param cacheName Cache name.
+ * @param nodeIdx Node index.
+ * @param curs Cursors.
+ * @param lsnrCfgs Listener configurations.
+ * @return Event queue
+ */
+ private BlockingQueue<CacheEntryEvent<?, ?>> registerListener(String cacheName,
+ int nodeIdx,
+ Collection<QueryCursor<?>> curs,
+ Collection<T2<Integer, MutableCacheEntryListenerConfiguration>> lsnrCfgs,
+ boolean sync) {
+ final BlockingQueue<CacheEntryEvent<?, ?>> evtsQueue = new ArrayBlockingQueue<>(50_000);
+
+ if (ThreadLocalRandom.current().nextBoolean()) {
+ MutableCacheEntryListenerConfiguration<QueryTestKey, QueryTestValue> lsnrCfg =
+ new MutableCacheEntryListenerConfiguration<>(
+ FactoryBuilder.factoryOf(new LocalNonSerialiseListener() {
+ @Override protected void onEvents(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts) {
+ for (CacheEntryEvent<?, ?> evt : evts)
+ evtsQueue.add(evt);
+ }
+ }),
+ createFilterFactory(),
+ true,
+ sync
+ );
+
+ grid(nodeIdx).cache(cacheName).registerCacheEntryListener((CacheEntryListenerConfiguration)lsnrCfg);
+
+ lsnrCfgs.add(new T2<Integer, MutableCacheEntryListenerConfiguration>(nodeIdx, lsnrCfg));
+ }
+ else {
+ ContinuousQuery<QueryTestKey, QueryTestValue> qry = new ContinuousQuery<>();
+
+ qry.setLocalListener(new CacheEntryUpdatedListener<QueryTestKey, QueryTestValue>() {
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
+ for (CacheEntryEvent<?, ?> evt : evts)
+ evtsQueue.add(evt);
+ }
+ });
+
+ qry.setRemoteFilterFactory(createFilterFactory());
+
+ QueryCursor<?> cur = grid(nodeIdx).cache(cacheName).query(qry);
+
+ curs.add(cur);
+ }
+
+ return evtsQueue;
+ }
+
+ /**
+ * @return Filter factory.
+ */
+ @NotNull protected Factory<? extends CacheEntryEventFilter<QueryTestKey, QueryTestValue>> createFilterFactory() {
+ return new FilterFactory();
+ }
+
+ /**
+ * @param rnd Random generator.
+ * @param evtsQueues Events queue.
+ * @param expData Expected cache data.
+ * @param partCntr Partition counter.
+ * @param cache Cache.
+ * @throws Exception If failed.
+ */
+ private void randomUpdate(
+ Random rnd,
+ List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues,
+ ConcurrentMap<Object, Object> expData,
+ Map<Integer, Long> partCntr,
+ IgniteCache<Object, Object> cache)
+ throws Exception {
+ Object key = new QueryTestKey(rnd.nextInt(KEYS));
+ Object newVal = value(rnd);
+ Object oldVal = expData.get(key);
+
+ int op = rnd.nextInt(11);
+
+ Ignite ignite = cache.unwrap(Ignite.class);
+
+ Transaction tx = null;
+
+ if (cache.getConfiguration(CacheConfiguration.class).getAtomicityMode() == TRANSACTIONAL && rnd.nextBoolean())
+ tx = ignite.transactions().txStart(txRandomConcurrency(rnd), txRandomIsolation(rnd));
+
+ try {
+ // log.info("Random operation [key=" + key + ", op=" + op + ']');
+
+ switch (op) {
+ case 0: {
+ cache.put(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
+
+ expData.put(key, newVal);
+
+ break;
+ }
+
+ case 1: {
+ cache.getAndPut(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
+
+ expData.put(key, newVal);
+
+ break;
+ }
+
+ case 2: {
+ cache.remove(key);
+
+ if (tx != null)
+ tx.commit();
+
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, null, oldVal);
+
+ expData.remove(key);
+
+ break;
+ }
+
+ case 3: {
+ cache.getAndRemove(key);
+
+ if (tx != null)
+ tx.commit();
+
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, null, oldVal);
+
+ expData.remove(key);
+
+ break;
+ }
+
+ case 4: {
+ cache.invoke(key, new EntrySetValueProcessor(newVal, rnd.nextBoolean()));
+
+ if (tx != null)
+ tx.commit();
+
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
+
+ expData.put(key, newVal);
+
+ break;
+ }
+
+ case 5: {
+ cache.invoke(key, new EntrySetValueProcessor(null, rnd.nextBoolean()));
+
+ if (tx != null)
+ tx.commit();
+
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, null, oldVal);
+
+ expData.remove(key);
+
+ break;
+ }
+
+ case 6: {
+ cache.putIfAbsent(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ if (oldVal == null) {
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, null);
+
+ expData.put(key, newVal);
+ }
+ else
+ checkNoEvent(evtsQueues);
+
+ break;
+ }
+
+ case 7: {
+ cache.getAndPutIfAbsent(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ if (oldVal == null) {
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, null);
+
+ expData.put(key, newVal);
+ }
+ else
+ checkNoEvent(evtsQueues);
+
+ break;
+ }
+
+ case 8: {
+ cache.replace(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ if (oldVal != null) {
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
+
+ expData.put(key, newVal);
+ }
+ else
+ checkNoEvent(evtsQueues);
+
+ break;
+ }
+
+ case 9: {
+ cache.getAndReplace(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ if (oldVal != null) {
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
+
+ expData.put(key, newVal);
+ }
+ else
+ checkNoEvent(evtsQueues);
+
+ break;
+ }
+
+ case 10: {
+ if (oldVal != null) {
+ Object replaceVal = value(rnd);
+
+ boolean success = replaceVal.equals(oldVal);
+
+ if (success) {
+ cache.replace(key, replaceVal, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ updatePartitionCounter(cache, key, partCntr);
+
+ waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
+
+ expData.put(key, newVal);
+ }
+ else {
+ cache.replace(key, replaceVal, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ checkNoEvent(evtsQueues);
+ }
+ }
+ else {
+ cache.replace(key, value(rnd), newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ checkNoEvent(evtsQueues);
+ }
+
+ break;
+ }
+
+ default:
+ fail("Op:" + op);
+ }
+ }
+ finally {
+ if (tx != null)
+ tx.close();
+ }
+ }
+
+ /**
+ * @param rnd {@link Random}.
+ * @return {@link TransactionIsolation}.
+ */
+ private TransactionIsolation txRandomIsolation(Random rnd) {
+ int val = rnd.nextInt(3);
+
+ if (val == 0)
+ return READ_COMMITTED;
+ else if (val == 1)
+ return REPEATABLE_READ;
+ else
+ return SERIALIZABLE;
+ }
+
+ /**
+ * @param rnd {@link Random}.
+ * @return {@link TransactionConcurrency}.
+ */
+ private TransactionConcurrency txRandomConcurrency(Random rnd) {
+ return rnd.nextBoolean() ? TransactionConcurrency.OPTIMISTIC : TransactionConcurrency.PESSIMISTIC;
+ }
+
+ /**
+ * @param cache Cache.
+ * @param key Key
+ * @param cntrs Partition counters.
+ */
+ private void updatePartitionCounter(IgniteCache<Object, Object> cache, Object key, Map<Integer, Long> cntrs) {
+ Affinity<Object> aff = cache.unwrap(Ignite.class).affinity(cache.getName());
+
+ int part = aff.partition(key);
+
+ Long partCntr = cntrs.get(part);
+
+ if (partCntr == null)
+ partCntr = 0L;
+
+ cntrs.put(part, ++partCntr);
+ }
+
+ /**
+ * @param rnd Random generator.
+ * @return Cache value.
+ */
+ private static Object value(Random rnd) {
+ return new QueryTestValue(rnd.nextInt(VALS));
+ }
+
+ /**
+ * @param evtsQueues Event queue.
+ * @param partCntrs Partition counters.
+ * @param aff Affinity function.
+ * @param key Key.
+ * @param val Value.
+ * @param oldVal Old value.
+ * @throws Exception If failed.
+ */
+ private void waitAndCheckEvent(List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues,
+ Map<Integer, Long> partCntrs,
+ Affinity<Object> aff,
+ Object key,
+ Object val,
+ Object oldVal)
+ throws Exception {
+ if ((val == null && oldVal == null
+ || (val != null && !isAccepted((QueryTestValue)val)))) {
+ checkNoEvent(evtsQueues);
+
+ return;
+ }
+
+ for (BlockingQueue<CacheEntryEvent<?, ?>> evtsQueue : evtsQueues) {
+ CacheEntryEvent<?, ?> evt = evtsQueue.poll(5, SECONDS);
+
+ assertNotNull("Failed to wait for event [key=" + key + ", val=" + val + ", oldVal=" + oldVal + ']', evt);
+ assertEquals(key, evt.getKey());
+ assertEquals(val, evt.getValue());
+ assertEquals(oldVal, evt.getOldValue());
+
+ long cntr = partCntrs.get(aff.partition(key));
+ CacheQueryEntryEvent qryEntryEvt = evt.unwrap(CacheQueryEntryEvent.class);
+
+ assertNotNull(cntr);
+ assertNotNull(qryEntryEvt);
+
+ assertEquals(cntr, qryEntryEvt.getPartitionUpdateCounter());
+ }
+ }
+
+ /**
+ * @param evtsQueues Event queue.
+ * @throws Exception If failed.
+ */
+ private void checkNoEvent(List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues) throws Exception {
+ for (BlockingQueue<CacheEntryEvent<?, ?>> evtsQueue : evtsQueues) {
+ CacheEntryEvent<?, ?> evt = evtsQueue.poll(50, MILLISECONDS);
+
+ assertNull(evt);
+ }
+ }
+
+ /**
+ *
+ */
+ protected static class NonSerializableFilter
+ implements CacheEntryEventSerializableFilter<CacheContinuousQueryRandomOperationsTest.QueryTestKey,
+ CacheContinuousQueryRandomOperationsTest.QueryTestValue>, Externalizable {
+ /** */
+ public NonSerializableFilter() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> evt) {
+ return isAccepted(evt.getValue());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ fail("Entry filter should not be marshaled.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ fail("Entry filter should not be marshaled.");
+ }
+
+ /**
+ * @param val Value.
+ * @return {@code True} if value is even.
+ */
+ public static boolean isAccepted(QueryTestValue val) {
+ return val == null || val.val1 % 2 == 0;
+ }
+ }
+
+ /**
+ *
+ */
+ protected static class SerializableFilter implements CacheEntryEventSerializableFilter<Integer, Integer> {
+ /** */
+ public SerializableFilter() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends Integer, ? extends Integer> evt)
+ throws CacheEntryListenerException {
+ return isAccepted(evt.getValue());
+ }
+
+ /**
+ * @return {@code True} if value is even.
+ */
+ public static boolean isAccepted(Integer val) {
+ return val == null || val % 2 == 0;
+ }
+ }
+
+ /**
+ *
+ */
+ protected static class FilterFactory implements Factory<NonSerializableFilter> {
+ /** {@inheritDoc} */
+ @Override public NonSerializableFilter create() {
+ return new NonSerializableFilter();
+ }
+ }
+
+ /**
+ *
+ */
+ public abstract class LocalNonSerialiseListener implements
+ CacheEntryUpdatedListener<QueryTestKey, QueryTestValue>,
+ CacheEntryCreatedListener<QueryTestKey, QueryTestValue>,
+ CacheEntryExpiredListener<QueryTestKey, QueryTestValue>,
+ CacheEntryRemovedListener<QueryTestKey, QueryTestValue>,
+ Externalizable {
+ /** */
+ public LocalNonSerialiseListener() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onCreated(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
+ onEvents(evts);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onExpired(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
+ onEvents(evts);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onRemoved(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
+ onEvents(evts);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
+ onEvents(evts);
+ }
+
+ /**
+ * @param evts Events.
+ */
+ protected abstract void onEvents(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> evts);
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ throw new UnsupportedOperationException("Failed. Listener should not be marshaled.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ throw new UnsupportedOperationException("Failed. Listener should not be unmarshaled.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterTest.java
deleted file mode 100644
index 55340d5..0000000
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryFilterTest.java
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.cache.query.continuous;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ThreadLocalRandom;
-import javax.cache.configuration.CacheEntryListenerConfiguration;
-import javax.cache.configuration.Factory;
-import javax.cache.configuration.FactoryBuilder;
-import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
-import javax.cache.event.CacheEntryCreatedListener;
-import javax.cache.event.CacheEntryEvent;
-import javax.cache.event.CacheEntryExpiredListener;
-import javax.cache.event.CacheEntryListenerException;
-import javax.cache.event.CacheEntryRemovedListener;
-import javax.cache.event.CacheEntryUpdatedListener;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
-import org.apache.ignite.cache.affinity.Affinity;
-import org.apache.ignite.cache.query.CacheQueryEntryEvent;
-import org.apache.ignite.cache.query.ContinuousQuery;
-import org.apache.ignite.cache.query.QueryCursor;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.internal.util.typedef.T2;
-import org.apache.ignite.transactions.Transaction;
-import org.apache.ignite.transactions.TransactionConcurrency;
-import org.apache.ignite.transactions.TransactionIsolation;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
-import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
-import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
-import static org.apache.ignite.cache.CacheMode.REPLICATED;
-import static org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFactoryFilterTest.NonSerializableFilter.isAccepted;
-import static org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryRandomOperationsTest.ContinuousDeploy.CLIENT;
-import static org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryRandomOperationsTest.ContinuousDeploy.SERVER;
-import static org.apache.ignite.transactions.TransactionIsolation.READ_COMMITTED;
-import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
-import static org.apache.ignite.transactions.TransactionIsolation.SERIALIZABLE;
-
-/**
- *
- */
-public class CacheContinuousQueryFactoryFilterTest extends CacheContinuousQueryRandomOperationsTest {
- /** */
- private static final int NODES = 5;
-
- /** */
- private static final int KEYS = 50;
-
- /** */
- private static final int VALS = 10;
-
- /** */
- public static final int ITERATION_CNT = 40;
-
- /**
- * @throws Exception If failed.
- */
- public void testInternalQuery() throws Exception {
- CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED,
- 1,
- ATOMIC,
- ONHEAP_TIERED,
- false);
-
- final IgniteCache<Object, Object> cache = grid(0).createCache(ccfg);
-
- UUID uuid = null;
-
- try {
- for (int i = 0; i < 10; i++)
- cache.put(i, i);
-
- final CountDownLatch latch = new CountDownLatch(5);
-
- CacheEntryUpdatedListener lsnr = new CacheEntryUpdatedListener() {
- @Override public void onUpdated(Iterable iterable) throws CacheEntryListenerException {
- for (Object evt : iterable) {
- latch.countDown();
-
- log.info("Received event: " + evt);
- }
- }
- };
-
- uuid = grid(0).context().cache().cache(cache.getName()).context().continuousQueries()
- .executeInternalQuery(lsnr, new SerializableFilter(), false, true, true);
-
- for (int i = 10; i < 20; i++)
- cache.put(i, i);
-
- assertTrue(latch.await(3, SECONDS));
- }
- finally {
- if (uuid != null)
- grid(0).context().cache().cache(cache.getName()).context().continuousQueries()
- .cancelInternalQuery(uuid);
-
- grid(0).destroyCache(ccfg.getName());
- }
- }
-
- /** {@inheritDoc} */
- @Override protected void doTestContinuousQuery(CacheConfiguration<Object, Object> ccfg, ContinuousDeploy deploy)
- throws Exception {
- ignite(0).createCache(ccfg);
-
- try {
- long seed = System.currentTimeMillis();
-
- Random rnd = new Random(seed);
-
- log.info("Random seed: " + seed);
-
- List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues = new ArrayList<>();
-
- Collection<QueryCursor<?>> curs = new ArrayList<>();
-
- Collection<T2<Integer, MutableCacheEntryListenerConfiguration>> lsnrCfgs = new ArrayList<>();
-
- if (deploy == CLIENT)
- evtsQueues.add(registerListener(ccfg.getName(), NODES - 1, curs, lsnrCfgs, rnd.nextBoolean()));
- else if (deploy == SERVER)
- evtsQueues.add(registerListener(ccfg.getName(), rnd.nextInt(NODES - 1), curs, lsnrCfgs,
- rnd.nextBoolean()));
- else {
- boolean isSync = rnd.nextBoolean();
-
- for (int i = 0; i < NODES - 1; i++)
- evtsQueues.add(registerListener(ccfg.getName(), i, curs, lsnrCfgs, isSync));
- }
-
- ConcurrentMap<Object, Object> expData = new ConcurrentHashMap<>();
-
- Map<Integer, Long> partCntr = new ConcurrentHashMap<>();
-
- try {
- for (int i = 0; i < ITERATION_CNT; i++) {
- if (i % 10 == 0)
- log.info("Iteration: " + i);
-
- for (int idx = 0; idx < NODES; idx++)
- randomUpdate(rnd, evtsQueues, expData, partCntr, grid(idx).cache(ccfg.getName()));
- }
- }
- finally {
- for (QueryCursor<?> cur : curs)
- cur.close();
-
- for (T2<Integer, MutableCacheEntryListenerConfiguration> e : lsnrCfgs)
- grid(e.get1()).cache(ccfg.getName()).deregisterCacheEntryListener(e.get2());
- }
- }
- finally {
- ignite(0).destroyCache(ccfg.getName());
- }
- }
-
- /**
- * @param cacheName Cache name.
- * @param nodeIdx Node index.
- * @param curs Cursors.
- * @param lsnrCfgs Listener configurations.
- * @return Event queue
- */
- private BlockingQueue<CacheEntryEvent<?, ?>> registerListener(String cacheName,
- int nodeIdx,
- Collection<QueryCursor<?>> curs,
- Collection<T2<Integer, MutableCacheEntryListenerConfiguration>> lsnrCfgs,
- boolean sync) {
- final BlockingQueue<CacheEntryEvent<?, ?>> evtsQueue = new ArrayBlockingQueue<>(50_000);
-
- if (ThreadLocalRandom.current().nextBoolean()) {
- MutableCacheEntryListenerConfiguration<QueryTestKey, QueryTestValue> lsnrCfg =
- new MutableCacheEntryListenerConfiguration<>(
- FactoryBuilder.factoryOf(new LocalNonSerialiseListener() {
- @Override protected void onEvents(Iterable<CacheEntryEvent<? extends QueryTestKey,
- ? extends QueryTestValue>> evts) {
- for (CacheEntryEvent<?, ?> evt : evts)
- evtsQueue.add(evt);
- }
- }),
- new FilterFactory(),
- true,
- sync
- );
-
- grid(nodeIdx).cache(cacheName).registerCacheEntryListener((CacheEntryListenerConfiguration)lsnrCfg);
-
- lsnrCfgs.add(new T2<Integer, MutableCacheEntryListenerConfiguration>(nodeIdx, lsnrCfg));
- }
- else {
- ContinuousQuery<QueryTestKey, QueryTestValue> qry = new ContinuousQuery<>();
-
- qry.setLocalListener(new CacheEntryUpdatedListener<QueryTestKey, QueryTestValue>() {
- @Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
- ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
- for (CacheEntryEvent<?, ?> evt : evts)
- evtsQueue.add(evt);
- }
- });
-
- qry.setRemoteFilterFactory(new FilterFactory());
-
- QueryCursor<?> cur = grid(nodeIdx).cache(cacheName).query(qry);
-
- curs.add(cur);
- }
-
- return evtsQueue;
- }
-
- /**
- * @param rnd Random generator.
- * @param evtsQueues Events queue.
- * @param expData Expected cache data.
- * @param partCntr Partition counter.
- * @param cache Cache.
- * @throws Exception If failed.
- */
- private void randomUpdate(
- Random rnd,
- List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues,
- ConcurrentMap<Object, Object> expData,
- Map<Integer, Long> partCntr,
- IgniteCache<Object, Object> cache)
- throws Exception {
- Object key = new QueryTestKey(rnd.nextInt(KEYS));
- Object newVal = value(rnd);
- Object oldVal = expData.get(key);
-
- int op = rnd.nextInt(11);
-
- Ignite ignite = cache.unwrap(Ignite.class);
-
- Transaction tx = null;
-
- if (cache.getConfiguration(CacheConfiguration.class).getAtomicityMode() == TRANSACTIONAL && rnd.nextBoolean())
- tx = ignite.transactions().txStart(txRandomConcurrency(rnd), txRandomIsolation(rnd));
-
- try {
- // log.info("Random operation [key=" + key + ", op=" + op + ']');
-
- switch (op) {
- case 0: {
- cache.put(key, newVal);
-
- if (tx != null)
- tx.commit();
-
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
-
- expData.put(key, newVal);
-
- break;
- }
-
- case 1: {
- cache.getAndPut(key, newVal);
-
- if (tx != null)
- tx.commit();
-
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
-
- expData.put(key, newVal);
-
- break;
- }
-
- case 2: {
- cache.remove(key);
-
- if (tx != null)
- tx.commit();
-
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, null, oldVal);
-
- expData.remove(key);
-
- break;
- }
-
- case 3: {
- cache.getAndRemove(key);
-
- if (tx != null)
- tx.commit();
-
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, null, oldVal);
-
- expData.remove(key);
-
- break;
- }
-
- case 4: {
- cache.invoke(key, new EntrySetValueProcessor(newVal, rnd.nextBoolean()));
-
- if (tx != null)
- tx.commit();
-
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
-
- expData.put(key, newVal);
-
- break;
- }
-
- case 5: {
- cache.invoke(key, new EntrySetValueProcessor(null, rnd.nextBoolean()));
-
- if (tx != null)
- tx.commit();
-
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, null, oldVal);
-
- expData.remove(key);
-
- break;
- }
-
- case 6: {
- cache.putIfAbsent(key, newVal);
-
- if (tx != null)
- tx.commit();
-
- if (oldVal == null) {
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, null);
-
- expData.put(key, newVal);
- }
- else
- checkNoEvent(evtsQueues);
-
- break;
- }
-
- case 7: {
- cache.getAndPutIfAbsent(key, newVal);
-
- if (tx != null)
- tx.commit();
-
- if (oldVal == null) {
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, null);
-
- expData.put(key, newVal);
- }
- else
- checkNoEvent(evtsQueues);
-
- break;
- }
-
- case 8: {
- cache.replace(key, newVal);
-
- if (tx != null)
- tx.commit();
-
- if (oldVal != null) {
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
-
- expData.put(key, newVal);
- }
- else
- checkNoEvent(evtsQueues);
-
- break;
- }
-
- case 9: {
- cache.getAndReplace(key, newVal);
-
- if (tx != null)
- tx.commit();
-
- if (oldVal != null) {
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
-
- expData.put(key, newVal);
- }
- else
- checkNoEvent(evtsQueues);
-
- break;
- }
-
- case 10: {
- if (oldVal != null) {
- Object replaceVal = value(rnd);
-
- boolean success = replaceVal.equals(oldVal);
-
- if (success) {
- cache.replace(key, replaceVal, newVal);
-
- if (tx != null)
- tx.commit();
-
- updatePartitionCounter(cache, key, partCntr);
-
- waitAndCheckEvent(evtsQueues, partCntr, affinity(cache), key, newVal, oldVal);
-
- expData.put(key, newVal);
- }
- else {
- cache.replace(key, replaceVal, newVal);
-
- if (tx != null)
- tx.commit();
-
- checkNoEvent(evtsQueues);
- }
- }
- else {
- cache.replace(key, value(rnd), newVal);
-
- if (tx != null)
- tx.commit();
-
- checkNoEvent(evtsQueues);
- }
-
- break;
- }
-
- default:
- fail("Op:" + op);
- }
- } finally {
- if (tx != null)
- tx.close();
- }
- }
-
- /**
- * @param rnd {@link Random}.
- * @return {@link TransactionIsolation}.
- */
- private TransactionIsolation txRandomIsolation(Random rnd) {
- int val = rnd.nextInt(3);
-
- if (val == 0)
- return READ_COMMITTED;
- else if (val == 1)
- return REPEATABLE_READ;
- else
- return SERIALIZABLE;
- }
-
- /**
- * @param rnd {@link Random}.
- * @return {@link TransactionConcurrency}.
- */
- private TransactionConcurrency txRandomConcurrency(Random rnd) {
- return rnd.nextBoolean() ? TransactionConcurrency.OPTIMISTIC : TransactionConcurrency.PESSIMISTIC;
- }
-
- /**
- * @param cache Cache.
- * @param key Key
- * @param cntrs Partition counters.
- */
- private void updatePartitionCounter(IgniteCache<Object, Object> cache, Object key, Map<Integer, Long> cntrs) {
- Affinity<Object> aff = cache.unwrap(Ignite.class).affinity(cache.getName());
-
- int part = aff.partition(key);
-
- Long partCntr = cntrs.get(part);
-
- if (partCntr == null)
- partCntr = 0L;
-
- cntrs.put(part, ++partCntr);
- }
-
- /**
- * @param rnd Random generator.
- * @return Cache value.
- */
- private static Object value(Random rnd) {
- return new QueryTestValue(rnd.nextInt(VALS));
- }
-
- /**
- * @param evtsQueues Event queue.
- * @param partCntrs Partition counters.
- * @param aff Affinity function.
- * @param key Key.
- * @param val Value.
- * @param oldVal Old value.
- * @throws Exception If failed.
- */
- private void waitAndCheckEvent(List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues,
- Map<Integer, Long> partCntrs,
- Affinity<Object> aff,
- Object key,
- Object val,
- Object oldVal)
- throws Exception {
- if ((val == null && oldVal == null
- || (val != null && !isAccepted((QueryTestValue)val)))) {
- checkNoEvent(evtsQueues);
-
- return;
- }
-
- for (BlockingQueue<CacheEntryEvent<?, ?>> evtsQueue : evtsQueues) {
- CacheEntryEvent<?, ?> evt = evtsQueue.poll(5, SECONDS);
-
- assertNotNull("Failed to wait for event [key=" + key + ", val=" + val + ", oldVal=" + oldVal + ']', evt);
- assertEquals(key, evt.getKey());
- assertEquals(val, evt.getValue());
- assertEquals(oldVal, evt.getOldValue());
-
- long cntr = partCntrs.get(aff.partition(key));
- CacheQueryEntryEvent qryEntryEvt = evt.unwrap(CacheQueryEntryEvent.class);
-
- assertNotNull(cntr);
- assertNotNull(qryEntryEvt);
-
- assertEquals(cntr, qryEntryEvt.getPartitionUpdateCounter());
- }
- }
-
- /**
- * @param evtsQueues Event queue.
- * @throws Exception If failed.
- */
- private void checkNoEvent(List<BlockingQueue<CacheEntryEvent<?, ?>>> evtsQueues) throws Exception {
- for (BlockingQueue<CacheEntryEvent<?, ?>> evtsQueue : evtsQueues) {
- CacheEntryEvent<?, ?> evt = evtsQueue.poll(50, MILLISECONDS);
-
- assertNull(evt);
- }
- }
-
- /**
- *
- */
- protected static class NonSerializableFilter
- implements CacheEntryEventSerializableFilter<CacheContinuousQueryRandomOperationsTest.QueryTestKey,
- CacheContinuousQueryRandomOperationsTest.QueryTestValue>, Externalizable {
- /** */
- public NonSerializableFilter() {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public boolean evaluate(CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> event)
- throws CacheEntryListenerException {
- return isAccepted(event.getValue());
- }
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- fail("Entry filter should not be marshaled.");
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- fail("Entry filter should not be marshaled.");
- }
-
- /**
- * @return {@code True} if value is even.
- */
- public static boolean isAccepted(QueryTestValue val) {
- return val == null || val.val1 % 2 == 0;
- }
- }
-
- /**
- *
- */
- protected static class SerializableFilter implements CacheEntryEventSerializableFilter<Integer, Integer>{
- /** */
- public SerializableFilter() {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public boolean evaluate(CacheEntryEvent<? extends Integer, ? extends Integer> event)
- throws CacheEntryListenerException {
- return isAccepted(event.getValue());
- }
-
- /**
- * @return {@code True} if value is even.
- */
- public static boolean isAccepted(Integer val) {
- return val == null || val % 2 == 0;
- }
- }
-
- /**
- *
- */
- protected static class FilterFactory implements Factory<NonSerializableFilter> {
- @Override public NonSerializableFilter create() {
- return new NonSerializableFilter();
- }
- }
-
- /**
- *
- */
- public abstract class LocalNonSerialiseListener implements
- CacheEntryUpdatedListener<QueryTestKey, QueryTestValue>,
- CacheEntryCreatedListener<QueryTestKey, QueryTestValue>,
- CacheEntryExpiredListener<QueryTestKey, QueryTestValue>,
- CacheEntryRemovedListener<QueryTestKey, QueryTestValue>,
- Externalizable {
- /** */
- public LocalNonSerialiseListener() {
- // No-op.
- }
-
- /** {@inheritDoc} */
- @Override public void onCreated(Iterable<CacheEntryEvent<? extends QueryTestKey,
- ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
- onEvents(evts);
- }
-
- /** {@inheritDoc} */
- @Override public void onExpired(Iterable<CacheEntryEvent<? extends QueryTestKey,
- ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
- onEvents(evts);
- }
-
- /** {@inheritDoc} */
- @Override public void onRemoved(Iterable<CacheEntryEvent<? extends QueryTestKey,
- ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
- onEvents(evts);
- }
-
- /** {@inheritDoc} */
- @Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
- ? extends QueryTestValue>> evts) throws CacheEntryListenerException {
- onEvents(evts);
- }
-
- /**
- * @param evts Events.
- */
- protected abstract void onEvents(Iterable<CacheEntryEvent<? extends QueryTestKey,
- ? extends QueryTestValue>> evts);
-
- /** {@inheritDoc} */
- @Override public void writeExternal(ObjectOutput out) throws IOException {
- throw new UnsupportedOperationException("Failed. Listener should not be marshaled.");
- }
-
- /** {@inheritDoc} */
- @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- throw new UnsupportedOperationException("Failed. Listener should not be unmarshaled.");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
index 4226537..083367c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
@@ -81,6 +81,7 @@ import org.apache.ignite.internal.util.typedef.PA;
import org.apache.ignite.internal.util.typedef.PAX;
import org.apache.ignite.internal.util.typedef.T2;
import org.apache.ignite.internal.util.typedef.T3;
+import org.apache.ignite.lang.IgniteAsyncCallback;
import org.apache.ignite.lang.IgniteInClosure;
import org.apache.ignite.lang.IgniteOutClosure;
import org.apache.ignite.plugin.extensions.communication.Message;
@@ -99,7 +100,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
-import static org.apache.ignite.cache.CacheMemoryMode.*;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
import static org.apache.ignite.cache.CacheMode.REPLICATED;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
@@ -167,6 +168,13 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
}
/**
+ * @return Async callback flag.
+ */
+ protected boolean asyncCallback() {
+ return false;
+ }
+
+ /**
* @return Near cache configuration.
*/
protected NearCacheConfiguration nearCacheConfiguration() {
@@ -476,7 +484,8 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
for (int j = 0; j < 50; ++j) {
ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
- final CacheEventListener3 lsnr = new CacheEventListener3();
+ final CacheEventListener3 lsnr = asyncCallback() ? new CacheEventAsyncListener3()
+ : new CacheEventListener3();
qry.setLocalListener(lsnr);
@@ -560,7 +569,7 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
- final CacheEventListener3 lsnr = new CacheEventListener3();
+ final CacheEventListener3 lsnr = asyncCallback() ? new CacheEventAsyncListener3() : new CacheEventListener3();
qry.setLocalListener(lsnr);
@@ -721,7 +730,7 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
- final CacheEventListener3 lsnr = new CacheEventListener3();
+ final CacheEventListener3 lsnr = asyncCallback() ? new CacheEventAsyncListener3() : new CacheEventListener3();
qry.setLocalListener(lsnr);
@@ -841,7 +850,8 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
Affinity<Object> aff = qryClient.affinity(null);
- CacheEventListener1 lsnr = new CacheEventListener1(false);
+ CacheEventListener1 lsnr = asyncCallback() ? new CacheEventAsyncListener1(false)
+ : new CacheEventListener1(false);
ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
@@ -1545,7 +1555,7 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
qry.setLocalListener(lsnr);
- qry.setRemoteFilter(new CacheEventFilter());
+ qry.setRemoteFilter(asyncCallback() ? new CacheEventAsyncFilter() : new CacheEventFilter());
QueryCursor<?> cur = qryClnCache.query(qry);
@@ -1639,7 +1649,7 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
newQry.setLocalListener(dinLsnr);
- newQry.setRemoteFilter(new CacheEventFilter());
+ newQry.setRemoteFilter(asyncCallback() ? new CacheEventAsyncFilter() : new CacheEventFilter());
dinQry = qryClnCache.query(newQry);
@@ -1786,7 +1796,7 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
final IgniteCache<Object, Object> qryClnCache = qryCln.cache(null);
- final CacheEventListener2 lsnr = new CacheEventListener2();
+ final CacheEventListener2 lsnr = asyncCallback() ? new CacheEventAsyncListener2() : new CacheEventListener2();
ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
@@ -2144,6 +2154,19 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
/**
*
*/
+ @IgniteAsyncCallback
+ private static class CacheEventAsyncListener1 extends CacheEventListener1 {
+ /**
+ * @param saveAll Save all events flag.
+ */
+ CacheEventAsyncListener1(boolean saveAll) {
+ super(saveAll);
+ }
+ }
+
+ /**
+ *
+ */
private static class CacheEventListener1 implements CacheEntryUpdatedListener<Object, Object> {
/** */
private volatile CountDownLatch latch;
@@ -2208,6 +2231,14 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
/**
*
*/
+ @IgniteAsyncCallback
+ private static class CacheEventAsyncListener2 extends CacheEventListener2 {
+ // No-op.
+ }
+
+ /**
+ *
+ */
private static class CacheEventListener2 implements CacheEntryUpdatedListener<Object, Object> {
/** */
@LoggerResource
@@ -2275,6 +2306,14 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
/**
*
*/
+ @IgniteAsyncCallback
+ public static class CacheEventAsyncListener3 extends CacheEventListener3 {
+ // No-op.
+ }
+
+ /**
+ *
+ */
public static class CacheEventListener3 implements CacheEntryUpdatedListener<Object, Object>,
CacheEntryEventSerializableFilter<Object, Object> {
/** Keys. */
@@ -2303,6 +2342,14 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
/**
*
*/
+ @IgniteAsyncCallback
+ private static class CacheEventAsyncFilter extends CacheEventFilter {
+ // No-op.
+ }
+
+ /**
+ *
+ */
public static class CacheEventFilter implements CacheEntryEventSerializableFilter<Object, Object> {
/** {@inheritDoc} */
@Override public boolean evaluate(CacheEntryEvent<?, ?> evt) throws CacheEntryListenerException {
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryLostPartitionTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryLostPartitionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryLostPartitionTest.java
index 025dd80..b469a86 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryLostPartitionTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryLostPartitionTest.java
@@ -60,6 +60,12 @@ public class CacheContinuousQueryLostPartitionTest extends GridCommonAbstractTes
super.beforeTest();
startGridsMultiThreaded(2);
+
+ assert GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return grid(0).cluster().nodes().size() == 2;
+ }
+ }, 10000L);
}
/** {@inheritDoc} */
@@ -140,6 +146,14 @@ public class CacheContinuousQueryLostPartitionTest extends GridCommonAbstractTes
// node2 now becomes the primary for the key.
stopGrid(0);
+ final int prevSize = grid(1).cluster().nodes().size();
+
+ GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return prevSize - 1 == grid(1).cluster().nodes().size();
+ }
+ }, 5000L);
+
cache2.put(key, "2");
// Sanity check.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOperationFromCallbackTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOperationFromCallbackTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOperationFromCallbackTest.java
new file mode 100644
index 0000000..0d027a9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryOperationFromCallbackTest.java
@@ -0,0 +1,627 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.configuration.FactoryBuilder;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.cache.CacheEntryProcessor;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.PA;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteAsyncCallback;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.PRIMARY_SYNC;
+
+/**
+ *
+ */
+public class CacheContinuousQueryOperationFromCallbackTest extends GridCommonAbstractTest {
+ /** */
+ public static final int KEYS = 10;
+
+ /** */
+ public static final int KEYS_FROM_CALLBACK = 20;
+
+ /** */
+ private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final int NODES = 5;
+
+ /** */
+ public static final int ITERATION_CNT = 20;
+
+ /** */
+ public static final int SYSTEM_POOL_SIZE = 10;
+
+ /** */
+ private boolean client;
+
+ /** */
+ private static AtomicInteger filterCbCntr = new AtomicInteger(0);
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ cfg.setSystemThreadPoolSize(SYSTEM_POOL_SIZE);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+ ((TcpCommunicationSpi)cfg.getCommunicationSpi()).setSharedMemoryPort(-1);
+
+ cfg.setClientMode(client);
+
+ MemoryEventStorageSpi storeSpi = new MemoryEventStorageSpi();
+ storeSpi.setExpireCount(100);
+
+ cfg.setEventStorageSpi(storeSpi);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(NODES - 1);
+
+ client = true;
+
+ startGrid(NODES - 1);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ super.beforeTest();
+
+ filterCbCntr.set(0);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testAtomicTwoBackups() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, ATOMIC, FULL_SYNC);
+
+ doTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxTwoBackupsFilter() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, FULL_SYNC);
+
+ doTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxTwoBackupsFilterPrimary() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, PRIMARY_SYNC);
+
+ doTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxReplicatedFilter() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED, 0, TRANSACTIONAL, FULL_SYNC);
+
+ doTest(ccfg, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxTwoBackup() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, FULL_SYNC);
+
+ doTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxReplicated() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED, 2, TRANSACTIONAL, FULL_SYNC);
+
+ doTest(ccfg, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testTxReplicatedPrimary() throws Exception {
+ CacheConfiguration<Object, Object> ccfg = cacheConfiguration(REPLICATED, 2, TRANSACTIONAL, PRIMARY_SYNC);
+
+ doTest(ccfg, true);
+ }
+
+ /**
+ * @param ccfg Cache configuration.
+ * @throws Exception If failed.
+ */
+ protected void doTest(final CacheConfiguration ccfg, boolean fromLsnr) throws Exception {
+ ignite(0).createCache(ccfg);
+
+ List<QueryCursor<?>> qries = new ArrayList<>();
+
+ assertEquals(0, filterCbCntr.get());
+
+ try {
+ List<Set<T2<QueryTestKey, QueryTestValue>>> rcvdEvts = new ArrayList<>(NODES);
+ List<Set<T2<QueryTestKey, QueryTestValue>>> evtsFromCallbacks = new ArrayList<>(NODES);
+
+ final AtomicInteger qryCntr = new AtomicInteger(0);
+
+ final AtomicInteger cbCntr = new AtomicInteger(0);
+
+ final int threadCnt = SYSTEM_POOL_SIZE * 2;
+
+ for (int idx = 0; idx < NODES; idx++) {
+ Set<T2<QueryTestKey, QueryTestValue>> evts = Collections.
+ newSetFromMap(new ConcurrentHashMap<T2<QueryTestKey, QueryTestValue>, Boolean>());
+ Set<T2<QueryTestKey, QueryTestValue>> evtsFromCb = Collections.
+ newSetFromMap(new ConcurrentHashMap<T2<QueryTestKey, QueryTestValue>, Boolean>());
+
+ IgniteCache<Object, Object> cache = grid(idx).getOrCreateCache(ccfg.getName());
+
+ ContinuousQuery qry = new ContinuousQuery();
+
+ qry.setLocalListener(new TestCacheAsyncEventListener(evts, evtsFromCb,
+ fromLsnr ? cache : null, qryCntr, cbCntr));
+
+ if (!fromLsnr)
+ qry.setRemoteFilterFactory(
+ FactoryBuilder.factoryOf(new CacheTestRemoteFilterAsync(ccfg.getName())));
+
+ rcvdEvts.add(evts);
+ evtsFromCallbacks.add(evtsFromCb);
+
+ QueryCursor qryCursor = cache.query(qry);
+
+ qries.add(qryCursor);
+ }
+
+ IgniteInternalFuture<Long> f = GridTestUtils.runMultiThreadedAsync(new Runnable() {
+ @Override public void run() {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ for (int i = 0; i < ITERATION_CNT; i++) {
+ IgniteCache<QueryTestKey, QueryTestValue> cache =
+ grid(rnd.nextInt(NODES)).cache(ccfg.getName());
+
+ QueryTestKey key = new QueryTestKey(rnd.nextInt(KEYS));
+
+ boolean startTx = cache.getConfiguration(CacheConfiguration.class).getAtomicityMode() ==
+ TRANSACTIONAL && rnd.nextBoolean();
+
+ Transaction tx = null;
+
+ if (startTx)
+ tx = cache.unwrap(Ignite.class).transactions().txStart();
+
+ try {
+ if ((cache.get(key) == null) || rnd.nextBoolean())
+ cache.invoke(key, new IncrementTestEntryProcessor());
+ else {
+ QueryTestValue val;
+ QueryTestValue newVal;
+
+ do {
+ val = cache.get(key);
+
+ newVal = val == null ?
+ new QueryTestValue(0) : new QueryTestValue(val.val1 + 1);
+ }
+ while (!cache.replace(key, val, newVal));
+ }
+ }
+ finally {
+ if (tx != null)
+ tx.commit();
+ }
+ }
+ }
+ }, threadCnt, "put-thread");
+
+ f.get(30, TimeUnit.SECONDS);
+
+ assert GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return qryCntr.get() >= ITERATION_CNT * threadCnt * NODES;
+ }
+ }, TimeUnit.MINUTES.toMillis(2));
+
+ for (Set<T2<QueryTestKey, QueryTestValue>> set : rcvdEvts)
+ checkEvents(set, ITERATION_CNT * threadCnt, grid(0).cache(ccfg.getName()), false);
+
+ if (fromLsnr) {
+ final int expCnt = qryCntr.get() * NODES * KEYS_FROM_CALLBACK;
+
+ boolean res = GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return cbCntr.get() >= expCnt;
+ }
+ }, TimeUnit.SECONDS.toMillis(60));
+
+ assertTrue("Failed to wait events [exp=" + expCnt + ", act=" + cbCntr.get() + "]", res);
+
+ assertEquals(expCnt, cbCntr.get());
+
+ for (Set<T2<QueryTestKey, QueryTestValue>> set : evtsFromCallbacks)
+ checkEvents(set, qryCntr.get() * KEYS_FROM_CALLBACK, grid(0).cache(ccfg.getName()), true);
+ }
+ else {
+ final int expInvkCnt = ITERATION_CNT * threadCnt *
+ (ccfg.getCacheMode() != REPLICATED ? (ccfg.getBackups() + 1) : NODES - 1) * NODES;
+
+ GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return filterCbCntr.get() >= expInvkCnt;
+ }
+ }, TimeUnit.SECONDS.toMillis(60));
+
+ assertEquals(expInvkCnt, filterCbCntr.get());
+
+ for (Set<T2<QueryTestKey, QueryTestValue>> set : evtsFromCallbacks)
+ checkEvents(set, expInvkCnt * KEYS_FROM_CALLBACK, grid(0).cache(ccfg.getName()), true);
+ }
+ }
+ finally {
+ for (QueryCursor<?> qry : qries)
+ qry.close();
+
+ ignite(0).destroyCache(ccfg.getName());
+ }
+ }
+
+ /**
+ * @param expCnt Expected count.
+ * @param cache Cache.
+ * @param set Received events.
+ * @throws Exception If failed.
+ */
+ private void checkEvents(final Set<T2<QueryTestKey, QueryTestValue>> set, final int expCnt, IgniteCache cache,
+ boolean cb) throws Exception {
+ assertTrue("Expected size: " + expCnt + ", actual: " + set.size(), GridTestUtils.waitForCondition(new PA() {
+ @Override public boolean apply() {
+ return set.size() >= expCnt;
+ }
+ }, 10000L));
+
+ int startKey = cb ? KEYS : 0;
+ int endKey = cb ? KEYS + KEYS_FROM_CALLBACK : KEYS;
+
+ for (int i = startKey; i < endKey; i++) {
+ QueryTestKey key = new QueryTestKey(i);
+
+ QueryTestValue maxVal = (QueryTestValue)cache.get(key);
+
+ for (int val = 0; val <= maxVal.val1; val++)
+ assertTrue(set.remove(new T2<>(key, new QueryTestValue(val))));
+ }
+
+ assertTrue(set.isEmpty());
+ }
+
+ /**
+ *
+ */
+ private static class IncrementTestEntryProcessor implements
+ CacheEntryProcessor<QueryTestKey, QueryTestValue, Object> {
+ /** {@inheritDoc} */
+ @Override public Object process(MutableEntry<QueryTestKey, QueryTestValue> entry, Object... arguments)
+ throws EntryProcessorException {
+ if (entry.exists())
+ entry.setValue(new QueryTestValue(entry.getValue().val1 + 1));
+ else
+ entry.setValue(new QueryTestValue(0));
+
+ return null;
+ }
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ private static class CacheTestRemoteFilterAsync implements
+ CacheEntryEventSerializableFilter<QueryTestKey, QueryTestValue> {
+ /** */
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** */
+ private String cacheName;
+
+ /**
+ * @param cacheName Cache name.
+ */
+ public CacheTestRemoteFilterAsync(String cacheName) {
+ this.cacheName = cacheName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> e)
+ throws CacheEntryListenerException {
+ if (e.getKey().compareTo(new QueryTestKey(KEYS)) < 0) {
+ IgniteCache<QueryTestKey, QueryTestValue> cache = ignite.cache(cacheName);
+
+ if (ThreadLocalRandom.current().nextBoolean()) {
+ Set<QueryTestKey> keys = new LinkedHashSet<>();
+
+ for (int key = KEYS; key < KEYS + KEYS_FROM_CALLBACK; key++)
+ keys.add(new QueryTestKey(key));
+
+ cache.invokeAll(keys, new IncrementTestEntryProcessor());
+ }
+ else {
+ for (int key = KEYS; key < KEYS + KEYS_FROM_CALLBACK; key++)
+ cache.invoke(new QueryTestKey(key), new IncrementTestEntryProcessor());
+ }
+
+ filterCbCntr.incrementAndGet();
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ private static class TestCacheAsyncEventListener
+ implements CacheEntryUpdatedListener<QueryTestKey, QueryTestValue> {
+ /** */
+ private final Set<T2<QueryTestKey, QueryTestValue>> rcvsEvts;
+
+ /** */
+ private final AtomicInteger cntr;
+
+ /** */
+ private final AtomicInteger cbCntr;
+
+ /** */
+ private final Set<T2<QueryTestKey, QueryTestValue>> evtsFromCb;
+
+ /** */
+ private IgniteCache<QueryTestKey, QueryTestValue> cache;
+
+ /**
+ * @param rcvsEvts Set for received events.
+ * @param evtsFromCb Set for received events.
+ * @param cache Ignite cache.
+ * @param cntr Received events counter.
+ * @param cbCntr Received events counter from callbacks.
+ */
+ public TestCacheAsyncEventListener(Set<T2<QueryTestKey, QueryTestValue>> rcvsEvts,
+ Set<T2<QueryTestKey, QueryTestValue>> evtsFromCb,
+ @Nullable IgniteCache cache,
+ AtomicInteger cntr,
+ AtomicInteger cbCntr) {
+ this.rcvsEvts = rcvsEvts;
+ this.evtsFromCb = evtsFromCb;
+ this.cache = cache;
+ this.cntr = cntr;
+ this.cbCntr = cbCntr;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> evts)
+ throws CacheEntryListenerException {
+ for (CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> e : evts) {
+ if (e.getKey().compareTo(new QueryTestKey(KEYS)) < 0) {
+ rcvsEvts.add(new T2<>(e.getKey(), e.getValue()));
+
+ cntr.incrementAndGet();
+
+ if (cache != null) {
+ if (ThreadLocalRandom.current().nextBoolean()) {
+ Set<QueryTestKey> keys = new LinkedHashSet<>();
+
+ for (int key = KEYS; key < KEYS + KEYS_FROM_CALLBACK; key++)
+ keys.add(new QueryTestKey(key));
+
+ cache.invokeAll(keys, new IncrementTestEntryProcessor());
+ }
+ else {
+ for (int key = KEYS; key < KEYS + KEYS_FROM_CALLBACK; key++)
+ cache.invoke(new QueryTestKey(key), new IncrementTestEntryProcessor());
+ }
+ }
+ }
+ else {
+ evtsFromCb.add(new T2<>(e.getKey(), e.getValue()));
+
+ cbCntr.incrementAndGet();
+ }
+ }
+ }
+ }
+
+ /**
+ * @param cacheMode Cache mode.
+ * @param backups Number of backups.
+ * @param atomicityMode Cache atomicity mode.
+ * @param writeMode Write sync mode.
+ * @return Cache configuration.
+ */
+ protected CacheConfiguration<Object, Object> cacheConfiguration(
+ CacheMode cacheMode,
+ int backups,
+ CacheAtomicityMode atomicityMode,
+ CacheWriteSynchronizationMode writeMode) {
+ CacheConfiguration<Object, Object> ccfg = new CacheConfiguration<>();
+
+ ccfg.setName("test-cache-" + atomicityMode + "-" + cacheMode + "-" + writeMode + "-" + backups);
+ ccfg.setAtomicityMode(atomicityMode);
+ ccfg.setCacheMode(cacheMode);
+ ccfg.setWriteSynchronizationMode(writeMode);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+
+ if (cacheMode == PARTITIONED)
+ ccfg.setBackups(backups);
+
+ return ccfg;
+ }
+
+ /**
+ *
+ */
+ public static class QueryTestKey implements Serializable, Comparable {
+ /** */
+ private final Integer key;
+
+ /**
+ * @param key Key.
+ */
+ public QueryTestKey(Integer key) {
+ this.key = key;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ QueryTestKey that = (QueryTestKey)o;
+
+ return key.equals(that.key);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return key.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(QueryTestKey.class, this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compareTo(Object o) {
+ return key - ((QueryTestKey)o).key;
+ }
+ }
+
+ /**
+ *
+ */
+ public static class QueryTestValue implements Serializable {
+ /** */
+ @GridToStringInclude
+ protected final Integer val1;
+
+ /** */
+ @GridToStringInclude
+ protected final String val2;
+
+ /**
+ * @param val Value.
+ */
+ public QueryTestValue(Integer val) {
+ this.val1 = val;
+ this.val2 = String.valueOf(val);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ QueryTestValue that = (QueryTestValue) o;
+
+ return val1.equals(that.val1) && val2.equals(that.val2);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = val1.hashCode();
+
+ res = 31 * res + val2.hashCode();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(QueryTestValue.class, this);
+ }
+ }
+}
[5/7] ignite git commit: IGNITE-2004 Fixed "Asynchronous execution of
ContinuousQuery's remote filter & local list".
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
index c01f636..9efc456 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
@@ -54,11 +54,13 @@ import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
import org.apache.ignite.internal.processors.cache.GridCacheManagerAdapter;
import org.apache.ignite.internal.processors.cache.KeyCacheObject;
+import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateFuture;
import org.apache.ignite.internal.processors.continuous.GridContinuousHandler;
import org.apache.ignite.internal.processors.continuous.GridContinuousProcessor;
import org.apache.ignite.internal.util.typedef.CI2;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteAsyncCallback;
import org.apache.ignite.lang.IgniteClosure;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.plugin.security.SecurityPermission;
@@ -166,23 +168,8 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
* @param key Entry key.
* @param partId Partition id.
* @param updCntr Updated counter.
- * @param topVer Topology version.
- */
- public void skipUpdateEvent(Map<UUID, CacheContinuousQueryListener> lsnrs,
- KeyCacheObject key,
- int partId,
- long updCntr,
- AffinityTopologyVersion topVer) {
- skipUpdateEvent(lsnrs, key, partId, updCntr, true, topVer);
- }
-
- /**
- * @param lsnrs Listeners to notify.
- * @param key Entry key.
- * @param partId Partition id.
- * @param updCntr Updated counter.
- * @param topVer Topology version.
* @param primary Primary.
+ * @param topVer Topology version.
*/
public void skipUpdateEvent(Map<UUID, CacheContinuousQueryListener> lsnrs,
KeyCacheObject key,
@@ -241,6 +228,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
* @param primary {@code True} if called on primary node.
* @param preload Whether update happened during preloading.
* @param updateCntr Update counter.
+ * @param fut Dht atomic future.
* @param topVer Topology version.
* @throws IgniteCheckedException In case of error.
*/
@@ -253,7 +241,9 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
boolean primary,
boolean preload,
long updateCntr,
- AffinityTopologyVersion topVer) throws IgniteCheckedException {
+ @Nullable GridDhtAtomicUpdateFuture fut,
+ AffinityTopologyVersion topVer
+ ) throws IgniteCheckedException {
Map<UUID, CacheContinuousQueryListener> lsnrCol = updateListeners(internal, preload);
if (lsnrCol != null) {
@@ -267,6 +257,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
primary,
preload,
updateCntr,
+ fut,
topVer);
}
}
@@ -282,6 +273,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
* @param preload Whether update happened during preloading.
* @param updateCntr Update counter.
* @param topVer Topology version.
+ * @param fut Dht atomic future.
* @throws IgniteCheckedException In case of error.
*/
public void onEntryUpdated(
@@ -294,6 +286,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
boolean primary,
boolean preload,
long updateCntr,
+ @Nullable GridDhtAtomicUpdateFuture fut,
AffinityTopologyVersion topVer)
throws IgniteCheckedException
{
@@ -347,7 +340,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
CacheContinuousQueryEvent evt = new CacheContinuousQueryEvent<>(
cctx.kernalContext().cache().jcache(cctx.name()), cctx, e0);
- lsnr.onEntryUpdated(evt, primary, recordIgniteEvt);
+ lsnr.onEntryUpdated(evt, primary, recordIgniteEvt, fut);
}
}
@@ -401,7 +394,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
CacheContinuousQueryEvent evt = new CacheContinuousQueryEvent(
cctx.kernalContext().cache().jcache(cctx.name()), cctx, e0);
- lsnr.onEntryUpdated(evt, primary, recordIgniteEvt);
+ lsnr.onEntryUpdated(evt, primary, recordIgniteEvt, null);
}
}
}
@@ -511,7 +504,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
return executeQuery0(
locLsnr,
new IgniteClosure<Boolean, CacheContinuousQueryHandler>() {
- @Override public CacheContinuousQueryHandler apply(Boolean aBoolean) {
+ @Override public CacheContinuousQueryHandler apply(Boolean v2) {
return new CacheContinuousQueryHandler(
cctx.name(),
TOPIC_CACHE.topic(topicPrefix, cctx.localNodeId(), seq.getAndIncrement()),
@@ -800,6 +793,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
}
/**
+ *
*/
private class JCacheQuery {
/** */
@@ -931,9 +925,9 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
/**
*
*/
- private static class JCacheQueryLocalListener<K, V> implements CacheEntryUpdatedListener<K, V> {
+ static class JCacheQueryLocalListener<K, V> implements CacheEntryUpdatedListener<K, V> {
/** */
- private final CacheEntryListener<K, V> impl;
+ final CacheEntryListener<K, V> impl;
/** */
private final IgniteLogger log;
@@ -957,28 +951,28 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
try {
switch (evt.getEventType()) {
case CREATED:
- assert impl instanceof CacheEntryCreatedListener;
+ assert impl instanceof CacheEntryCreatedListener : evt;
((CacheEntryCreatedListener<K, V>)impl).onCreated(singleton(evt));
break;
case UPDATED:
- assert impl instanceof CacheEntryUpdatedListener;
+ assert impl instanceof CacheEntryUpdatedListener : evt;
((CacheEntryUpdatedListener<K, V>)impl).onUpdated(singleton(evt));
break;
case REMOVED:
- assert impl instanceof CacheEntryRemovedListener;
+ assert impl instanceof CacheEntryRemovedListener : evt;
((CacheEntryRemovedListener<K, V>)impl).onRemoved(singleton(evt));
break;
case EXPIRED:
- assert impl instanceof CacheEntryExpiredListener;
+ assert impl instanceof CacheEntryExpiredListener : evt;
((CacheEntryExpiredListener<K, V>)impl).onExpired(singleton(evt));
@@ -1009,6 +1003,13 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
return evts;
}
+
+ /**
+ * @return {@code True} if listener should be executed in non-system thread.
+ */
+ protected boolean async() {
+ return U.hasAnnotation(impl, IgniteAsyncCallback.class);
+ }
}
/**
@@ -1019,7 +1020,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
private static final long serialVersionUID = 0L;
/** */
- private CacheEntryEventFilter impl;
+ protected CacheEntryEventFilter impl;
/** */
private byte types;
@@ -1072,6 +1073,13 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
}
/**
+ * @return {@code True} if filter should be executed in non-system thread.
+ */
+ protected boolean async() {
+ return U.hasAnnotation(impl, IgniteAsyncCallback.class);
+ }
+
+ /**
* @param evtType Type.
* @return Flag value.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/lang/IgniteAsyncCallback.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/IgniteAsyncCallback.java b/modules/core/src/main/java/org/apache/ignite/lang/IgniteAsyncCallback.java
new file mode 100644
index 0000000..1e04ce6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/lang/IgniteAsyncCallback.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.lang;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.cache.event.CacheEntryEventFilter;
+import javax.cache.event.CacheEntryListener;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.configuration.IgniteConfiguration;
+
+/**
+ * If callback has this annotation then it will be executing in another thread.
+ * <p>
+ * Currently this annotation is supported for:
+ * <ol>
+ * <li>{@link ContinuousQuery} - {@link CacheEntryUpdatedListener} and {@link CacheEntryEventFilter}.</li>
+ * </ol>
+ * <p>
+ * For example, if {@link CacheEntryEventFilter filter} or {@link CacheEntryListener}
+ * has the annotation then callbacks will be executing to asyncCallback thread pool. It allows to use cache API
+ * in a callbacks. This thread pool can be configured by {@link IgniteConfiguration#setAsyncCallbackPoolSize(int)}.
+ * <h1 class="header">Example</h1>
+ * As an example, suppose we have cache with {@code 'Person'} objects and we need
+ * to query all persons with salary above then 1000. Also remote filter will update some entries.
+ * <p>
+ * Here is the {@code Person} class:
+ * <pre name="code" class="java">
+ * public class Person {
+ * // Name.
+ * private String name;
+ *
+ * // Salary.
+ * private double salary;
+ *
+ * ...
+ * }
+ * </pre>
+ * <p>
+ * Here is the {@code ExampleCacheEntryFilter} class:
+ * <pre name="code" class="java">
+ * @IgniteAsyncCallback
+ * public class ExampleCacheEntryFilter implements CacheEntryEventFilter<Integer, Person> {
+ * @IgniteInstanceResource
+ * private Ignite ignite;
+ *
+ * // Continuous listener will be notified for persons with salary above 1000.
+ * // Filter increases salary for some person on 100. Without @IgniteAsyncCallback annotation
+ * // this operation is not safe.
+ * public boolean evaluate(CacheEntryEvent<? extends K, ? extends V> evt) throws CacheEntryListenerException {
+ * Person p = evt.getValue();
+ *
+ * if (p.getSalary() > 1000)
+ * return true;
+ *
+ * ignite.cache("Person").put(evt.getKey(), new Person(p.getName(), p.getSalary() + 100));
+ *
+ * return false;
+ * }
+ * }
+ * </pre>
+ * <p>
+ * Query with asynchronous callback execute as usually:
+ * <pre name="code" class="java">
+ * // Create new continuous query.
+ * ContinuousQuery<Long, Person> qry = new ContinuousQuery<>();
+ *
+ * // Callback that is called locally when update notifications are received.
+ * // It simply prints out information about all created persons.
+ * qry.setLocalListener((evts) -> {
+ * for (CacheEntryEvent<? extends Long, ? extends Person> e : evts) {
+ * Person p = e.getValue();
+ *
+ * System.out.println(p.getFirstName() + " " + p.getLastName() + "'s salary is " + p.getSalary());
+ * }
+ * });
+ *
+ * // Sets remote filter.
+ * qry.setRemoteFilterFactory(() -> new ExampleCacheEntryFilter());
+ *
+ * // Execute query.
+ * QueryCursor<Cache.Entry<Long, Person>> cur = cache.query(qry);
+ * </pre>
+ *
+ * @see IgniteConfiguration#getAsyncCallbackPoolSize
+ * @see ContinuousQuery#getRemoteFilterFactory()
+ * @see ContinuousQuery#getLocalListener()
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface IgniteAsyncCallback {
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/thread/IgniteStripedThreadPoolExecutor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/thread/IgniteStripedThreadPoolExecutor.java b/modules/core/src/main/java/org/apache/ignite/thread/IgniteStripedThreadPoolExecutor.java
index 35882b9..9f7c381 100644
--- a/modules/core/src/main/java/org/apache/ignite/thread/IgniteStripedThreadPoolExecutor.java
+++ b/modules/core/src/main/java/org/apache/ignite/thread/IgniteStripedThreadPoolExecutor.java
@@ -17,62 +17,63 @@
package org.apache.ignite.thread;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.LinkedList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.NotNull;
/**
* An {@link ExecutorService} that executes submitted tasks using pooled grid threads.
*/
public class IgniteStripedThreadPoolExecutor implements ExecutorService {
/** */
- public static final int DFLT_SEG_POOL_SIZE = 8;
-
- /** */
- public static final int DFLT_CONCUR_LVL = 16;
-
- /** */
private final ExecutorService[] execs;
- /** */
- private final int segShift;
-
- /** */
- private final int segMask;
-
/**
+ * Create striped thread pool.
*
+ * @param concurrentLvl Concurrency level.
+ * @param gridName Node name.
+ * @param threadNamePrefix Thread name prefix.
*/
- public IgniteStripedThreadPoolExecutor() {
- execs = new ExecutorService[DFLT_CONCUR_LVL];
-
- ThreadFactory factory = new IgniteThreadFactory(null);
-
- for (int i = 0; i < DFLT_CONCUR_LVL; i++)
- execs[i] = Executors.newFixedThreadPool(DFLT_SEG_POOL_SIZE, factory);
+ public IgniteStripedThreadPoolExecutor(int concurrentLvl, String gridName, String threadNamePrefix) {
+ execs = new ExecutorService[concurrentLvl];
- // Find power-of-two sizes best matching arguments
- int sshift = 0;
- int ssize = 1;
+ ThreadFactory factory = new IgniteThreadFactory(gridName, threadNamePrefix);
- while (ssize < DFLT_CONCUR_LVL) {
- ++sshift;
-
- ssize <<= 1;
- }
+ for (int i = 0; i < concurrentLvl; i++)
+ execs[i] = Executors.newSingleThreadExecutor(factory);
+ }
- segShift = 32 - sshift;
- segMask = ssize - 1;
+ /**
+ * Executes the given command at some time in the future. The command with the same {@code index}
+ * will be executed in the same thread.
+ *
+ * @param task the runnable task
+ * @param idx Striped index.
+ * @throws RejectedExecutionException if this task cannot be
+ * accepted for execution.
+ * @throws NullPointerException If command is null
+ */
+ public void execute(Runnable task, int idx) {
+ execs[threadId(idx)].execute(task);
+ }
+ /**
+ * @param idx Index.
+ * @return Stripped thread ID.
+ */
+ public int threadId(int idx) {
+ return idx < execs.length ? idx : idx % execs.length;
}
/** {@inheritDoc} */
@@ -83,7 +84,10 @@ public class IgniteStripedThreadPoolExecutor implements ExecutorService {
/** {@inheritDoc} */
@Override public List<Runnable> shutdownNow() {
- List<Runnable> res = new LinkedList<>();
+ if (execs.length == 0)
+ return Collections.emptyList();
+
+ List<Runnable> res = new ArrayList<>(execs.length);
for (ExecutorService exec : execs) {
for (Runnable r : exec.shutdownNow())
@@ -124,105 +128,45 @@ public class IgniteStripedThreadPoolExecutor implements ExecutorService {
}
/** {@inheritDoc} */
- @Override public <T> Future<T> submit(Callable<T> task) {
- return execForTask(task).submit(task);
+ @NotNull @Override public <T> Future<T> submit(Callable<T> task) {
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
- @Override public <T> Future<T> submit(Runnable task, T result) {
- return execForTask(task).submit(task, result);
+ @NotNull @Override public <T> Future<T> submit(Runnable task, T res) {
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
- @Override public Future<?> submit(Runnable task) {
- return execForTask(task).submit(task);
+ @NotNull @Override public Future<?> submit(Runnable task) {
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
- @Override public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
- throws InterruptedException {
- List<Future<T>> futs = new LinkedList<>();
-
- for (Callable<T> task : tasks)
- futs.add(execForTask(task).submit(task));
-
- boolean done = false;
-
- try {
- for (Future<T> fut : futs) {
- try {
- fut.get();
- }
- catch (ExecutionException | InterruptedException ignored) {
- // No-op.
- }
- }
-
- done = true;
-
- return futs;
- }
- finally {
- if (!done) {
- for (Future<T> fut : futs)
- fut.cancel(true);
- }
- }
+ @NotNull @Override public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
- @Override public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout,
- TimeUnit unit) throws InterruptedException {
- throw new RuntimeException("Not implemented.");
+ @NotNull @Override public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+ long timeout,
+ TimeUnit unit) {
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
- @Override public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException,
- ExecutionException {
- throw new RuntimeException("Not implemented.");
+ @NotNull @Override public <T> T invokeAny(Collection<? extends Callable<T>> tasks) {
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
- @Override public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
- throws InterruptedException, ExecutionException, TimeoutException {
- throw new RuntimeException("Not implemented.");
+ @Override public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
@Override public void execute(Runnable cmd) {
- execForTask(cmd).execute(cmd);
- }
-
- /**
- * Applies a supplemental hash function to a given hashCode, which
- * defends against poor quality hash functions. This is critical
- * because ConcurrentHashMap uses power-of-two length hash tables,
- * that otherwise encounter collisions for hashCodes that do not
- * differ in lower or upper bits.
- *
- * @param h Hash code.
- * @return Enhanced hash code.
- */
- private int hash(int h) {
- // Spread bits to regularize both segment and index locations,
- // using variant of single-word Wang/Jenkins hash.
- h += (h << 15) ^ 0xffffcd7d;
- h ^= (h >>> 10);
- h += (h << 3);
- h ^= (h >>> 6);
- h += (h << 2) + (h << 14);
- return h ^ (h >>> 16);
- }
-
- /**
- * @param cmd Command.
- * @return Service.
- */
- private <T> ExecutorService execForTask(T cmd) {
- assert cmd != null;
-
- //return execs[ThreadLocalRandom8.current().nextInt(DFLT_CONCUR_LVL)];
- return execs[(hash(cmd.hashCode()) >>> segShift) & segMask];
+ throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
index 6e404b4..a1153cd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
@@ -26,6 +26,7 @@ import javax.cache.processor.EntryProcessorResult;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.eviction.EvictableEntry;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateFuture;
import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -540,7 +541,8 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
UUID subjId,
String taskName,
@Nullable CacheObject prevVal,
- @Nullable Long updateCntr) throws IgniteCheckedException,
+ @Nullable Long updateCntr,
+ @Nullable GridDhtAtomicUpdateFuture fut) throws IgniteCheckedException,
GridCacheEntryRemovedException {
assert false;
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverAtomicPrimaryWriteOrderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverAtomicPrimaryWriteOrderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverAtomicPrimaryWriteOrderSelfTest.java
new file mode 100644
index 0000000..62fd984
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverAtomicPrimaryWriteOrderSelfTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicWriteOrderMode;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+
+/**
+ *
+ */
+public class CacheContinuousQueryAsyncFailoverAtomicPrimaryWriteOrderSelfTest
+ extends CacheContinuousQueryFailoverAbstractSelfTest {
+ /** {@inheritDoc} */
+ @Override protected CacheAtomicWriteOrderMode writeOrderMode() {
+ return PRIMARY;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected CacheMode cacheMode() {
+ return CacheMode.PARTITIONED;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected CacheAtomicityMode atomicityMode() {
+ return CacheAtomicityMode.ATOMIC;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean asyncCallback() {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxReplicatedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxReplicatedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxReplicatedSelfTest.java
new file mode 100644
index 0000000..4460498
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxReplicatedSelfTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import org.apache.ignite.cache.CacheMode;
+
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+
+/**
+ *
+ */
+public class CacheContinuousQueryAsyncFailoverTxReplicatedSelfTest extends CacheContinuousQueryFailoverTxSelfTest {
+ /** {@inheritDoc} */
+ @Override protected CacheMode cacheMode() {
+ return REPLICATED;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean asyncCallback() {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxSelfTest.java
new file mode 100644
index 0000000..8f0bd0e
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFailoverTxSelfTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+
+/**
+ *
+ */
+public class CacheContinuousQueryAsyncFailoverTxSelfTest extends CacheContinuousQueryFailoverAbstractSelfTest {
+ /** {@inheritDoc} */
+ @Override protected CacheMode cacheMode() {
+ return PARTITIONED;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected CacheAtomicityMode atomicityMode() {
+ return TRANSACTIONAL;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean asyncCallback() {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFilterListenerTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFilterListenerTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFilterListenerTest.java
new file mode 100644
index 0000000..0605bc8
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryAsyncFilterListenerTest.java
@@ -0,0 +1,986 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import java.io.Serializable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import javax.cache.configuration.FactoryBuilder;
+import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
+import javax.cache.event.CacheEntryCreatedListener;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.cache.CacheEntryProcessor;
+import org.apache.ignite.cache.CacheMemoryMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteAsyncCallback;
+import org.apache.ignite.lang.IgniteBiInClosure;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_VALUES;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
+/**
+ *
+ */
+public class CacheContinuousQueryAsyncFilterListenerTest extends GridCommonAbstractTest {
+ /** */
+ private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final int NODES = 5;
+
+ /** */
+ public static final int ITERATION_CNT = 100;
+
+ /** */
+ private boolean client;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+
+ cfg.setClientMode(client);
+
+ MemoryEventStorageSpi storeSpi = new MemoryEventStorageSpi();
+ storeSpi.setExpireCount(1000);
+
+ cfg.setEventStorageSpi(storeSpi);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(NODES - 1);
+
+ client = true;
+
+ startGrid(NODES - 1);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ ///
+ /// ASYNC FILTER AND LISTENER. TEST LISTENER.
+ ///
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerTx() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerTxJCacheApi() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerTxOffHeap() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerTxOffHeapJCacheApi() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerTxOffHeapValues() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_VALUES), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerAtomic() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, ATOMIC, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerAtomicJCacheApi() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, ATOMIC, ONHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerReplicatedAtomic() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(REPLICATED, 2, ATOMIC, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerReplicatedAtomicJCacheApi() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(REPLICATED, 2, ATOMIC, ONHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerReplicatedAtomicOffHeapValues() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(REPLICATED, 2, ATOMIC, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerAtomicOffHeap() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, ATOMIC, OFFHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerAtomicOffHeapValues() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, ATOMIC, OFFHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerAtomicWithoutBackup() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 0, ATOMIC, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerAtomicWithoutBackupJCacheApi() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 0, ATOMIC, ONHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListener() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerReplicated() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(REPLICATED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInListenerReplicatedJCacheApi() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(REPLICATED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, true);
+ }
+
+ ///
+ /// ASYNC FILTER AND LISTENER. TEST FILTER.
+ ///
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTx() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTxJCacheApi() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTxOffHeap() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTxOffHeapJCacheApi() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTxOffHeapValues() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_VALUES), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomic() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, ATOMIC, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicJCacheApi() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, ATOMIC, ONHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterReplicatedAtomic() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(REPLICATED, 2, ATOMIC, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicOffHeap() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, ATOMIC, OFFHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicOffHeapJCacheApi() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, ATOMIC, OFFHEAP_TIERED), true, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicOffHeapValues() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, ATOMIC, OFFHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicWithoutBackup() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 0, ATOMIC, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilter() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterReplicated() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(REPLICATED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterReplicatedJCacheApi() throws Exception {
+ testNonDeadLockInFilter(cacheConfiguration(REPLICATED, 2, TRANSACTIONAL, ONHEAP_TIERED), true, true, false);
+ }
+
+ ///
+ /// ASYNC LISTENER. TEST LISTENER.
+ ///
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTxSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTxOffHeapSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterTxOffHeapValuesSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, OFFHEAP_VALUES), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, ATOMIC, ONHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterReplicatedAtomicSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(REPLICATED, 2, ATOMIC, ONHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicOffHeapSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, ATOMIC, OFFHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicOffHeapValuesSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, ATOMIC, OFFHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterAtomicWithoutBackupSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 0, ATOMIC, ONHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(PARTITIONED, 2, TRANSACTIONAL, ONHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testNonDeadLockInFilterReplicatedSyncFilter() throws Exception {
+ testNonDeadLockInListener(cacheConfiguration(REPLICATED, 2, TRANSACTIONAL, ONHEAP_TIERED), false, true, false);
+ }
+
+ /**
+ * @param ccfg Cache configuration.
+ * @param asyncFltr Async filter.
+ * @param asyncLsnr Async listener.
+ * @param jcacheApi Use JCache api for registration entry update listener.
+ * @throws Exception If failed.
+ */
+ private void testNonDeadLockInListener(CacheConfiguration ccfg,
+ final boolean asyncFltr,
+ boolean asyncLsnr,
+ boolean jcacheApi) throws Exception {
+ ignite(0).createCache(ccfg);
+
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ try {
+ for (int i = 0; i < ITERATION_CNT; i++) {
+ log.info("Start iteration: " + i);
+
+ int nodeIdx = i % NODES;
+
+ final IgniteCache cache = grid(nodeIdx).cache(ccfg.getName());
+
+ final QueryTestKey key = NODES - 1 != nodeIdx ? affinityKey(cache) : new QueryTestKey(1);
+
+ final QueryTestValue val0 = new QueryTestValue(1);
+ final QueryTestValue newVal = new QueryTestValue(2);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final CountDownLatch evtFromLsnrLatch = new CountDownLatch(1);
+
+ IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> fltrClsr =
+ new IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>>() {
+ @Override public void apply(Ignite ignite, CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue> e) {
+ if (asyncFltr) {
+ assertFalse("Failed: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("sys-"));
+
+ assertTrue("Failed: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("callback-"));
+ }
+ }
+ };
+
+ IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> lsnrClsr =
+ new IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>>() {
+ @Override public void apply(Ignite ignite, CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue> e) {
+ IgniteCache<Object, Object> cache0 = ignite.cache(cache.getName());
+
+ QueryTestValue val = e.getValue();
+
+ if (val == null)
+ return;
+ else if (val.equals(newVal)) {
+ evtFromLsnrLatch.countDown();
+
+ return;
+ }
+ else if (!val.equals(val0))
+ return;
+
+ Transaction tx = null;
+
+ try {
+ if (cache0.getConfiguration(CacheConfiguration.class).getAtomicityMode() == TRANSACTIONAL)
+ tx = ignite.transactions().txStart(PESSIMISTIC, REPEATABLE_READ);
+
+ assertEquals(val, val0);
+
+ cache0.put(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ latch.countDown();
+ }
+ catch (Exception exp) {
+ log.error("Failed: ", exp);
+
+ throw new IgniteException(exp);
+ }
+ finally {
+ if (tx != null)
+ tx.close();
+ }
+ }
+ };
+
+ QueryCursor qry = null;
+ MutableCacheEntryListenerConfiguration<QueryTestKey, QueryTestValue> lsnrCfg = null;
+
+ CacheInvokeListener locLsnr = asyncLsnr ? new CacheInvokeListenerAsync(lsnrClsr)
+ : new CacheInvokeListener(lsnrClsr);
+
+ CacheEntryEventSerializableFilter<QueryTestKey, QueryTestValue> rmtFltr = asyncFltr ?
+ new CacheTestRemoteFilterAsync(fltrClsr) : new CacheTestRemoteFilter(fltrClsr);
+
+ if (jcacheApi) {
+ lsnrCfg = new MutableCacheEntryListenerConfiguration<>(
+ FactoryBuilder.factoryOf(locLsnr),
+ FactoryBuilder.factoryOf(rmtFltr),
+ true,
+ false
+ );
+
+ cache.registerCacheEntryListener(lsnrCfg);
+ }
+ else {
+ ContinuousQuery<QueryTestKey, QueryTestValue> conQry = new ContinuousQuery<>();
+
+ conQry.setLocalListener(locLsnr);
+
+ conQry.setRemoteFilterFactory(FactoryBuilder.factoryOf(rmtFltr));
+
+ qry = cache.query(conQry);
+ }
+
+ try {
+ if (rnd.nextBoolean())
+ cache.put(key, val0);
+ else {
+ cache.invoke(key, new CacheEntryProcessor() {
+ @Override public Object process(MutableEntry entry, Object... arguments)
+ throws EntryProcessorException {
+ entry.setValue(val0);
+
+ return null;
+ }
+ });
+ }
+
+ assertTrue("Failed to waiting event.", U.await(latch, 3, SECONDS));
+
+ assertEquals(cache.get(key), new QueryTestValue(2));
+
+ assertTrue("Failed to waiting event from listener.", U.await(latch, 3, SECONDS));
+ }
+ finally {
+ if (qry != null)
+ qry.close();
+
+ if (lsnrCfg != null)
+ cache.deregisterCacheEntryListener(lsnrCfg);
+ }
+
+ log.info("Iteration finished: " + i);
+ }
+ }
+ finally {
+ ignite(0).destroyCache(ccfg.getName());
+ }
+ }
+
+ /**
+ * @param ccfg Cache configuration.
+ * @param asyncFilter Async filter.
+ * @param asyncLsnr Async listener.
+ * @param jcacheApi Use JCache api for start update listener.
+ * @throws Exception If failed.
+ */
+ private void testNonDeadLockInFilter(CacheConfiguration ccfg,
+ final boolean asyncFilter,
+ final boolean asyncLsnr,
+ boolean jcacheApi) throws Exception {
+ ignite(0).createCache(ccfg);
+
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ try {
+ for (int i = 0; i < ITERATION_CNT; i++) {
+ log.info("Start iteration: " + i);
+
+ int nodeIdx = i % NODES;
+
+ final IgniteCache cache = grid(nodeIdx).cache(ccfg.getName());
+
+ final QueryTestKey key = NODES - 1 != nodeIdx ? affinityKey(cache) : new QueryTestKey(1);
+
+ final QueryTestValue val0 = new QueryTestValue(1);
+ final QueryTestValue newVal = new QueryTestValue(2);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final CountDownLatch evtFromLsnrLatch = new CountDownLatch(1);
+
+ IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> fltrClsr =
+ new IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>>() {
+ @Override public void apply(Ignite ignite, CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue> e) {
+ if (asyncFilter) {
+ assertFalse("Failed: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("sys-"));
+
+ assertTrue("Failed: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("callback-"));
+ }
+
+ IgniteCache<Object, Object> cache0 = ignite.cache(cache.getName());
+
+ QueryTestValue val = e.getValue();
+
+ if (val == null)
+ return;
+ else if (val.equals(newVal)) {
+ evtFromLsnrLatch.countDown();
+
+ return;
+ }
+ else if (!val.equals(val0))
+ return;
+
+ Transaction tx = null;
+
+ try {
+ if (cache0.getConfiguration(CacheConfiguration.class)
+ .getAtomicityMode() == TRANSACTIONAL)
+ tx = ignite.transactions().txStart(PESSIMISTIC, REPEATABLE_READ);
+
+ assertEquals(val, val0);
+
+ cache0.put(key, newVal);
+
+ if (tx != null)
+ tx.commit();
+
+ latch.countDown();
+ }
+ catch (Exception exp) {
+ log.error("Failed: ", exp);
+
+ throw new IgniteException(exp);
+ }
+ finally {
+ if (tx != null)
+ tx.close();
+ }
+ }
+ };
+
+ IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> lsnrClsr =
+ new IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>>() {
+ @Override public void apply(Ignite ignite, CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue> e) {
+ if (asyncLsnr) {
+ assertFalse("Failed: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("sys-"));
+
+ assertTrue("Failed: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("callback-"));
+ }
+
+ QueryTestValue val = e.getValue();
+
+ if (val == null || !val.equals(new QueryTestValue(1)))
+ return;
+
+ assertEquals(val, val0);
+
+ latch.countDown();
+ }
+ };
+
+
+ QueryCursor qry = null;
+ MutableCacheEntryListenerConfiguration<QueryTestKey, QueryTestValue> lsnrCfg = null;
+
+ CacheInvokeListener locLsnr = asyncLsnr ? new CacheInvokeListenerAsync(lsnrClsr)
+ : new CacheInvokeListener(lsnrClsr);
+
+ CacheEntryEventSerializableFilter<QueryTestKey, QueryTestValue> rmtFltr = asyncFilter ?
+ new CacheTestRemoteFilterAsync(fltrClsr) : new CacheTestRemoteFilter(fltrClsr);
+
+ if (jcacheApi) {
+ lsnrCfg = new MutableCacheEntryListenerConfiguration<>(
+ FactoryBuilder.factoryOf(locLsnr),
+ FactoryBuilder.factoryOf(rmtFltr),
+ true,
+ false
+ );
+
+ cache.registerCacheEntryListener(lsnrCfg);
+ }
+ else {
+ ContinuousQuery<QueryTestKey, QueryTestValue> conQry = new ContinuousQuery<>();
+
+ conQry.setLocalListener(locLsnr);
+
+ conQry.setRemoteFilterFactory(FactoryBuilder.factoryOf(rmtFltr));
+
+ qry = cache.query(conQry);
+ }
+
+ try {
+ if (rnd.nextBoolean())
+ cache.put(key, val0);
+ else
+ cache.invoke(key, new CacheEntryProcessor() {
+ @Override public Object process(MutableEntry entry, Object... arguments)
+ throws EntryProcessorException {
+ entry.setValue(val0);
+
+ return null;
+ }
+ });
+
+ assert U.await(latch, 3, SECONDS) : "Failed to waiting event.";
+
+ assertEquals(cache.get(key), new QueryTestValue(2));
+
+ assertTrue("Failed to waiting event from filter.", U.await(latch, 3, SECONDS));
+ }
+ finally {
+ if (qry != null)
+ qry.close();
+
+ if (lsnrCfg != null)
+ cache.deregisterCacheEntryListener(lsnrCfg);
+ }
+
+ log.info("Iteration finished: " + i);
+ }
+ }
+ finally {
+ ignite(0).destroyCache(ccfg.getName());
+ }
+ }
+
+ /**
+ * @param cache Ignite cache.
+ * @return Key.
+ */
+ private QueryTestKey affinityKey(IgniteCache cache) {
+ Affinity aff = affinity(cache);
+
+ for (int i = 0; i < 10_000; i++) {
+ QueryTestKey key = new QueryTestKey(i);
+
+ if (aff.isPrimary(localNode(cache), key))
+ return key;
+ }
+
+ throw new IgniteException("Failed to found primary key.");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long getTestTimeout() {
+ return TimeUnit.SECONDS.toMillis(15);
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ private static class CacheTestRemoteFilterAsync extends CacheTestRemoteFilter {
+ /**
+ * @param clsr Closure.
+ */
+ public CacheTestRemoteFilterAsync(
+ IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> clsr) {
+ super(clsr);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class CacheTestRemoteFilter implements
+ CacheEntryEventSerializableFilter<QueryTestKey, QueryTestValue> {
+ /** */
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** */
+ private IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> clsr;
+
+ /**
+ * @param clsr Closure.
+ */
+ public CacheTestRemoteFilter(IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> clsr) {
+ this.clsr = clsr;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> e)
+ throws CacheEntryListenerException {
+ clsr.apply(ignite, e);
+
+ return true;
+ }
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ private static class CacheInvokeListenerAsync extends CacheInvokeListener {
+ /**
+ * @param clsr Closure.
+ */
+ public CacheInvokeListenerAsync(
+ IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> clsr) {
+ super(clsr);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class CacheInvokeListener implements CacheEntryUpdatedListener<QueryTestKey, QueryTestValue>,
+ CacheEntryCreatedListener<QueryTestKey, QueryTestValue>, Serializable {
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** */
+ private IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue>> clsr;
+
+ /**
+ * @param clsr Closure.
+ */
+ public CacheInvokeListener(IgniteBiInClosure<Ignite, CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> clsr) {
+ this.clsr = clsr;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> events)
+ throws CacheEntryListenerException {
+ for (CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> e : events)
+ clsr.apply(ignite, e);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onCreated(Iterable<CacheEntryEvent<? extends QueryTestKey,
+ ? extends QueryTestValue>> events) throws CacheEntryListenerException {
+ for (CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> e : events)
+ clsr.apply(ignite, e);
+ }
+ }
+
+ /**
+ * @param cacheMode Cache mode.
+ * @param backups Number of backups.
+ * @param atomicityMode Cache atomicity mode.
+ * @param memoryMode Cache memory mode.
+ * @return Cache configuration.
+ */
+ protected CacheConfiguration<Object, Object> cacheConfiguration(
+ CacheMode cacheMode,
+ int backups,
+ CacheAtomicityMode atomicityMode,
+ CacheMemoryMode memoryMode) {
+ CacheConfiguration<Object, Object> ccfg = new CacheConfiguration<>();
+
+ ccfg.setName("test-cache-" + atomicityMode + "-" + cacheMode + "-" + memoryMode + "-" + backups);
+ ccfg.setAtomicityMode(atomicityMode);
+ ccfg.setCacheMode(cacheMode);
+ ccfg.setMemoryMode(memoryMode);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+
+ if (cacheMode == PARTITIONED)
+ ccfg.setBackups(backups);
+
+ return ccfg;
+ }
+
+ /**
+ *
+ */
+ public static class QueryTestKey implements Serializable, Comparable {
+ /** */
+ private final Integer key;
+
+ /**
+ * @param key Key.
+ */
+ public QueryTestKey(Integer key) {
+ this.key = key;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ QueryTestKey that = (QueryTestKey)o;
+
+ return key.equals(that.key);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return key.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(QueryTestKey.class, this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compareTo(Object o) {
+ return key - ((QueryTestKey)o).key;
+ }
+ }
+
+ /**
+ *
+ */
+ public static class QueryTestValue implements Serializable {
+ /** */
+ @GridToStringInclude
+ protected final Integer val1;
+
+ /** */
+ @GridToStringInclude
+ protected final String val2;
+
+ /**
+ * @param val Value.
+ */
+ public QueryTestValue(Integer val) {
+ this.val1 = val;
+ this.val2 = String.valueOf(val);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ QueryTestValue that = (QueryTestValue)o;
+
+ return val1.equals(that.val1) && val2.equals(that.val2);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = val1.hashCode();
+
+ res = 31 * res + val2.hashCode();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(QueryTestValue.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryAsyncFilterRandomOperationTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryAsyncFilterRandomOperationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryAsyncFilterRandomOperationTest.java
new file mode 100644
index 0000000..928cfda
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFactoryAsyncFilterRandomOperationTest.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import javax.cache.configuration.Factory;
+import javax.cache.configuration.FactoryBuilder;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryEventFilter;
+import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.lang.IgniteAsyncCallback;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ *
+ */
+public class CacheContinuousQueryFactoryAsyncFilterRandomOperationTest
+ extends CacheContinuousQueryFactoryFilterRandomOperationTest {
+ /** {@inheritDoc} */
+ @NotNull @Override protected Factory<? extends CacheEntryEventFilter<QueryTestKey, QueryTestValue>>
+ createFilterFactory() {
+ return new AsyncFilterFactory();
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ protected static class NonSerializableAsyncFilter implements
+ CacheEntryEventSerializableFilter<QueryTestKey, QueryTestValue>, Externalizable {
+ /** */
+ public NonSerializableAsyncFilter() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> evt) {
+ assertTrue("Failed. Current thread name: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("callback-"));
+
+ assertFalse("Failed. Current thread name: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("sys-"));
+
+ return isAccepted(evt.getValue());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ fail("Entry filter should not be marshaled.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ fail("Entry filter should not be marshaled.");
+ }
+
+ /**
+ * @param val Value.
+ * @return {@code True} if value is even.
+ */
+ public static boolean isAccepted(QueryTestValue val) {
+ return val == null || val.val1 % 2 == 0;
+ }
+ }
+
+ /**
+ *
+ */
+ protected static class AsyncFilterFactory implements Factory<NonSerializableAsyncFilter> {
+ /** {@inheritDoc} */
+ @Override public NonSerializableAsyncFilter create() {
+ return new NonSerializableAsyncFilter();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Factory<? extends CacheEntryEventFilter<QueryTestKey, QueryTestValue>> noOpFilterFactory() {
+ return FactoryBuilder.factoryOf(NoopAsyncFilter.class);
+ }
+
+ /**
+ *
+ */
+ @IgniteAsyncCallback
+ protected static class NoopAsyncFilter implements
+ CacheEntryEventSerializableFilter<QueryTestKey, QueryTestValue>, Externalizable {
+ /** */
+ public NoopAsyncFilter() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends QueryTestKey, ? extends QueryTestValue> evt) {
+ assertTrue("Failed. Current thread name: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("callback-"));
+
+ assertFalse("Failed. Current thread name: " + Thread.currentThread().getName(),
+ Thread.currentThread().getName().contains("sys-"));
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ // No-op.
+ }
+ }
+}
[6/7] ignite git commit: IGNITE-2004 Fixed "Asynchronous execution of
ContinuousQuery's remote filter & local list".
Posted by vo...@apache.org.
IGNITE-2004 Fixed "Asynchronous execution of ContinuousQuery's remote filter & local list".
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2ff64c2a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2ff64c2a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2ff64c2a
Branch: refs/heads/ignite-2523-1
Commit: 2ff64c2aa8f142f2918200e5ee85e6b7e83afbfa
Parents: a6de16d
Author: nikolay_tikhonov <nt...@gridgain.com>
Authored: Fri Apr 22 18:41:58 2016 +0300
Committer: nikolay_tikhonov <nt...@gridgain.com>
Committed: Fri Apr 22 18:41:58 2016 +0300
----------------------------------------------------------------------
.../CacheContinuousAsyncQueryExample.java | 138 +++
.../datagrid/CacheContinuousQueryExample.java | 13 +-
.../ignite/cache/query/ContinuousQuery.java | 27 +
.../configuration/IgniteConfiguration.java | 32 +
.../ignite/internal/GridKernalContext.java | 8 +
.../ignite/internal/GridKernalContextImpl.java | 12 +
.../apache/ignite/internal/IgniteKernal.java | 3 +
.../org/apache/ignite/internal/IgnitionEx.java | 16 +-
.../processors/cache/GridCacheEntryEx.java | 5 +-
.../processors/cache/GridCacheMapEntry.java | 49 +-
.../dht/atomic/GridDhtAtomicCache.java | 98 +-
.../dht/atomic/GridDhtAtomicUpdateFuture.java | 121 +--
.../dht/atomic/GridDhtAtomicUpdateRequest.java | 33 +-
.../distributed/near/GridNearAtomicCache.java | 3 +-
.../continuous/CacheContinuousQueryEvent.java | 7 +
.../continuous/CacheContinuousQueryHandler.java | 446 +++++++--
.../CacheContinuousQueryListener.java | 6 +-
.../continuous/CacheContinuousQueryManager.java | 62 +-
.../apache/ignite/lang/IgniteAsyncCallback.java | 111 +++
.../thread/IgniteStripedThreadPoolExecutor.java | 164 +--
.../processors/cache/GridCacheTestEntryEx.java | 4 +-
...FailoverAtomicPrimaryWriteOrderSelfTest.java | 50 +
...sQueryAsyncFailoverTxReplicatedSelfTest.java | 37 +
...eContinuousQueryAsyncFailoverTxSelfTest.java | 44 +
...eContinuousQueryAsyncFilterListenerTest.java | 986 +++++++++++++++++++
...ryFactoryAsyncFilterRandomOperationTest.java | 131 +++
...usQueryFactoryFilterRandomOperationTest.java | 725 ++++++++++++++
.../CacheContinuousQueryFactoryFilterTest.java | 714 --------------
...ContinuousQueryFailoverAbstractSelfTest.java | 63 +-
.../CacheContinuousQueryLostPartitionTest.java | 14 +
...ontinuousQueryOperationFromCallbackTest.java | 627 ++++++++++++
.../CacheContinuousQueryOrderingEventTest.java | 722 ++++++++++++++
...acheContinuousQueryRandomOperationsTest.java | 23 +
.../junits/GridTestKernalContext.java | 1 +
.../IgniteBinaryCacheQueryTestSuite.java | 1 -
.../IgniteCacheQuerySelfTestSuite3.java | 14 +-
.../IgniteCacheQuerySelfTestSuite4.java | 7 +
.../cache/CacheEntryEventAsyncProbe.java | 61 ++
.../yardstick/cache/CacheEntryEventProbe.java | 33 +-
39 files changed, 4408 insertions(+), 1203 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousAsyncQueryExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousAsyncQueryExample.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousAsyncQueryExample.java
new file mode 100644
index 0000000..4ac7ecb
--- /dev/null
+++ b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousAsyncQueryExample.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.examples.datagrid;
+
+import javax.cache.Cache;
+import javax.cache.configuration.Factory;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryEventFilter;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.ScanQuery;
+import org.apache.ignite.examples.ExampleNodeStartup;
+import org.apache.ignite.lang.IgniteAsyncCallback;
+import org.apache.ignite.lang.IgniteBiPredicate;
+import org.apache.ignite.resources.IgniteInstanceResource;
+
+/**
+ * This examples demonstrates asynchronous continuous query API.
+ * <p>
+ * Remote nodes should always be started with special configuration file which
+ * enables P2P class loading: {@code 'ignite.{sh|bat} examples/config/example-ignite.xml'}.
+ * <p>
+ * Alternatively you can run {@link ExampleNodeStartup} in another JVM which will
+ * start node with {@code examples/config/example-ignite.xml} configuration.
+ */
+public class CacheContinuousAsyncQueryExample {
+ /** Cache name. */
+ private static final String CACHE_NAME = CacheContinuousAsyncQueryExample.class.getSimpleName();
+
+ /**
+ * Executes example.
+ *
+ * @param args Command line arguments, none required.
+ * @throws Exception If example execution failed.
+ */
+ public static void main(String[] args) throws Exception {
+ try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) {
+ System.out.println();
+ System.out.println(">>> Cache continuous query example started.");
+
+ // Auto-close cache at the end of the example.
+ try (IgniteCache<Integer, String> cache = ignite.getOrCreateCache(CACHE_NAME)) {
+ int keyCnt = 20;
+
+ // These entries will be queried by initial predicate.
+ for (int i = 0; i < keyCnt; i++)
+ cache.put(i, Integer.toString(i));
+
+ // Create new continuous query.
+ ContinuousQuery<Integer, String> qry = new ContinuousQuery<>();
+
+ qry.setInitialQuery(new ScanQuery<>(new IgniteBiPredicate<Integer, String>() {
+ @Override public boolean apply(Integer key, String val) {
+ return key > 10;
+ }
+ }));
+
+ // Callback that is called locally when update notifications are received.
+ qry.setLocalListener(new CacheEntryUpdatedListener<Integer, String>() {
+ @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends String>> evts) {
+ for (CacheEntryEvent<? extends Integer, ? extends String> e : evts)
+ System.out.println("Updated entry [key=" + e.getKey() + ", val=" + e.getValue() + ']');
+ }
+ });
+
+ // This filter will be evaluated remotely on all nodes.
+ // Entry that pass this filter will be sent to the caller.
+ qry.setRemoteFilterFactory(new Factory<CacheEntryEventFilter<Integer, String>>() {
+ @Override public CacheEntryEventFilter<Integer, String> create() {
+ return new CacheEntryFilter();
+ }
+ });
+
+ // Execute query.
+ try (QueryCursor<Cache.Entry<Integer, String>> cur = cache.query(qry)) {
+ // Iterate through existing data.
+ for (Cache.Entry<Integer, String> e : cur)
+ System.out.println("Queried existing entry [key=" + e.getKey() + ", val=" + e.getValue() + ']');
+
+ // Add a few more keys and watch more query notifications.
+ for (int i = 0; i < keyCnt; i++)
+ cache.put(i, Integer.toString(i));
+
+ // Wait for a while while callback is notified about remaining puts.
+ Thread.sleep(2000);
+ }
+
+ // Iterate through entries which was updated from filter.
+ for (int i = 0; i < 10; i++)
+ System.out.println("Entry updated from filter [key=" + i + ", val=" + cache.get(i) + ']');
+ }
+ finally {
+ // Distributed cache could be removed from cluster only by #destroyCache() call.
+ ignite.destroyCache(CACHE_NAME);
+ }
+ }
+ }
+
+ /**
+ * Filter returns {@code true} for entries which have key bigger than 10.
+ */
+ @IgniteAsyncCallback
+ private static class CacheEntryFilter implements CacheEntryEventFilter<Integer, String> {
+ /** Ignite instance. */
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** {@inheritDoc} */
+ @Override public boolean evaluate(CacheEntryEvent<? extends Integer, ? extends String> e)
+ throws CacheEntryListenerException {
+ // This cache operation is safe because filter has Ignite AsyncCallback annotation.
+ if (e.getKey() < 10 && String.valueOf(e.getKey()).equals(e.getValue()))
+ ignite.cache(CACHE_NAME).put(e.getKey(), e.getValue() + "_less_than_10");
+
+ return e.getKey() > 10;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousQueryExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousQueryExample.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousQueryExample.java
index 59759af..aad5b5d 100644
--- a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousQueryExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheContinuousQueryExample.java
@@ -18,12 +18,13 @@
package org.apache.ignite.examples.datagrid;
import javax.cache.Cache;
+import javax.cache.configuration.Factory;
import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryEventFilter;
import javax.cache.event.CacheEntryUpdatedListener;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
-import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
import org.apache.ignite.cache.query.ContinuousQuery;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.ScanQuery;
@@ -81,9 +82,13 @@ public class CacheContinuousQueryExample {
// This filter will be evaluated remotely on all nodes.
// Entry that pass this filter will be sent to the caller.
- qry.setRemoteFilter(new CacheEntryEventSerializableFilter<Integer, String>() {
- @Override public boolean evaluate(CacheEntryEvent<? extends Integer, ? extends String> e) {
- return e.getKey() > 10;
+ qry.setRemoteFilterFactory(new Factory<CacheEntryEventFilter<Integer, String>>() {
+ @Override public CacheEntryEventFilter<Integer, String> create() {
+ return new CacheEntryEventFilter<Integer, String>() {
+ @Override public boolean evaluate(CacheEntryEvent<? extends Integer, ? extends String> e) {
+ return e.getKey() > 10;
+ }
+ };
}
});
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
index 3ea8f93..bbfe8cc 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
@@ -23,6 +23,8 @@ import javax.cache.event.CacheEntryEventFilter;
import javax.cache.event.CacheEntryUpdatedListener;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.lang.IgniteAsyncCallback;
/**
* API for configuring continuous cache queries.
@@ -92,6 +94,16 @@ import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
* Note that this works even if you didn't provide initial query. Cursor will
* be empty in this case, but it will still unregister listeners when {@link QueryCursor#close()}
* is called.
+ * <p>
+ * {@link IgniteAsyncCallback} annotation is supported for {@link CacheEntryEventFilter}
+ * (see {@link #setRemoteFilterFactory(Factory)}) and {@link CacheEntryUpdatedListener}
+ * (see {@link #setLocalListener(CacheEntryUpdatedListener)}).
+ * If filter and/or listener are annotated with {@link IgniteAsyncCallback} then annotated callback
+ * is executed in async callback pool (see {@link IgniteConfiguration#getAsyncCallbackPoolSize()})
+ * and notification order is kept the same as update order for given cache key.
+ *
+ * @see IgniteAsyncCallback
+ * @see IgniteConfiguration#getAsyncCallbackPoolSize()
*/
public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
/** */
@@ -173,9 +185,14 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
* <b>WARNING:</b> all operations that involve any kind of JVM-local or distributed locking (e.g.,
* synchronization or transactional cache operations), should be executed asynchronously without
* blocking the thread that called the callback. Otherwise, you can get deadlocks.
+ * <p>
+ * If local listener are annotated with {@link IgniteAsyncCallback} then it is executed in async callback pool
+ * (see {@link IgniteConfiguration#getAsyncCallbackPoolSize()}) that allow to perform a cache operations.
*
* @param locLsnr Local callback.
* @return {@code this} for chaining.
+ * @see IgniteAsyncCallback
+ * @see IgniteConfiguration#getAsyncCallbackPoolSize()
*/
public ContinuousQuery<K, V> setLocalListener(CacheEntryUpdatedListener<K, V> locLsnr) {
this.locLsnr = locLsnr;
@@ -198,11 +215,16 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
* <b>WARNING:</b> all operations that involve any kind of JVM-local or distributed locking
* (e.g., synchronization or transactional cache operations), should be executed asynchronously
* without blocking the thread that called the filter. Otherwise, you can get deadlocks.
+ * <p>
+ * If remote filter are annotated with {@link IgniteAsyncCallback} then it is executed in async callback
+ * pool (see {@link IgniteConfiguration#getAsyncCallbackPoolSize()}) that allow to perform a cache operations.
*
* @param rmtFilter Key-value filter.
* @return {@code this} for chaining.
*
* @deprecated Use {@link #setRemoteFilterFactory(Factory)} instead.
+ * @see IgniteAsyncCallback
+ * @see IgniteConfiguration#getAsyncCallbackPoolSize()
*/
@Deprecated
public ContinuousQuery<K, V> setRemoteFilter(CacheEntryEventSerializableFilter<K, V> rmtFilter) {
@@ -227,9 +249,14 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
* <b>WARNING:</b> all operations that involve any kind of JVM-local or distributed locking
* (e.g., synchronization or transactional cache operations), should be executed asynchronously
* without blocking the thread that called the filter. Otherwise, you can get deadlocks.
+ * <p>
+ * If remote filter are annotated with {@link IgniteAsyncCallback} then it is executed in async callback
+ * pool (see {@link IgniteConfiguration#getAsyncCallbackPoolSize()}) that allow to perform a cache operations.
*
* @param rmtFilterFactory Key-value filter factory.
* @return {@code this} for chaining.
+ * @see IgniteAsyncCallback
+ * @see IgniteConfiguration#getAsyncCallbackPoolSize()
*/
public ContinuousQuery<K, V> setRemoteFilterFactory(
Factory<? extends CacheEntryEventFilter<K, V>> rmtFilterFactory) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/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 e5bd05c..19b9a4d 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
@@ -43,6 +43,7 @@ import org.apache.ignite.events.Event;
import org.apache.ignite.events.EventType;
import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager;
import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteAsyncCallback;
import org.apache.ignite.lang.IgniteInClosure;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.lifecycle.LifecycleBean;
@@ -223,6 +224,9 @@ public class IgniteConfiguration {
/** Public pool size. */
private int pubPoolSize = DFLT_PUBLIC_THREAD_CNT;
+ /** Async Callback pool size. */
+ private int callbackPoolSize = DFLT_PUBLIC_THREAD_CNT;
+
/** System pool size. */
private int sysPoolSize = DFLT_SYSTEM_CORE_THREAD_CNT;
@@ -723,6 +727,20 @@ public class IgniteConfiguration {
}
/**
+ * Size of thread pool that is in charge of processing asynchronous callbacks.
+ * <p>
+ * This pool is used for callbacks annotated with {@link IgniteAsyncCallback}.
+ * <p>
+ * If not provided, executor service will have size {@link #DFLT_PUBLIC_THREAD_CNT}.
+ *
+ * @return Thread pool size to be used.
+ * @see IgniteAsyncCallback
+ */
+ public int getAsyncCallbackPoolSize() {
+ return callbackPoolSize;
+ }
+
+ /**
* Size of thread pool that is in charge of processing internal and Visor
* {@link ComputeJob GridJobs}.
* <p>
@@ -831,6 +849,20 @@ public class IgniteConfiguration {
}
/**
+ * Sets async callback thread pool size to use within grid.
+ *
+ * @param poolSize Thread pool size to use within grid.
+ * @return {@code this} for chaining.
+ * @see IgniteConfiguration#getAsyncCallbackPoolSize()
+ * @see IgniteAsyncCallback
+ */
+ public IgniteConfiguration setAsyncCallbackPoolSize(int poolSize) {
+ this.callbackPoolSize = poolSize;
+
+ return this;
+ }
+
+ /**
* Sets management thread pool size to use within grid.
*
* @param poolSize Thread pool size to use within grid.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
index b95d595..3eaef1e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
@@ -67,6 +67,7 @@ import org.apache.ignite.internal.util.IgniteExceptionRegistry;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.plugin.PluginNotFoundException;
import org.apache.ignite.plugin.PluginProvider;
+import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor;
/**
*
@@ -298,6 +299,13 @@ public interface GridKernalContext extends Iterable<GridComponent> {
public ExecutorService marshallerCachePool();
/**
+ * Gets async callback pool.
+ *
+ * @return Async callback pool.
+ */
+ public IgniteStripedThreadPoolExecutor asyncCallbackPool();
+
+ /**
* Gets cache object processor.
*
* @return Cache object processor.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index 753dbe8..79d67df 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -89,6 +89,7 @@ import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.plugin.PluginNotFoundException;
import org.apache.ignite.plugin.PluginProvider;
+import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_DAEMON;
@@ -305,6 +306,10 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
/** */
@GridToStringExclude
+ protected IgniteStripedThreadPoolExecutor callbackExecSvc;
+
+ /** */
+ @GridToStringExclude
private Map<String, Object> attrs = new HashMap<>();
/** */
@@ -379,6 +384,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
ExecutorService mgmtExecSvc,
ExecutorService igfsExecSvc,
ExecutorService restExecSvc,
+ IgniteStripedThreadPoolExecutor callbackExecSvc,
List<PluginProvider> plugins) throws IgniteCheckedException {
assert grid != null;
assert cfg != null;
@@ -395,6 +401,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
this.mgmtExecSvc = mgmtExecSvc;
this.igfsExecSvc = igfsExecSvc;
this.restExecSvc = restExecSvc;
+ this.callbackExecSvc = callbackExecSvc;
marshCtx = new MarshallerContextImpl(plugins);
@@ -746,6 +753,11 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
}
/** {@inheritDoc} */
+ @Override public IgniteStripedThreadPoolExecutor asyncCallbackPool() {
+ return callbackExecSvc;
+ }
+
+ /** {@inheritDoc} */
@Override public IgniteCacheObjectProcessor cacheObjects() {
return cacheObjProc;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 20795fc..d6655d9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -167,6 +167,7 @@ import org.apache.ignite.plugin.PluginProvider;
import org.apache.ignite.spi.IgniteSpi;
import org.apache.ignite.spi.IgniteSpiVersionCheckException;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
+import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_CONFIG_URL;
@@ -667,6 +668,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
ExecutorService mgmtExecSvc,
ExecutorService igfsExecSvc,
ExecutorService restExecSvc,
+ IgniteStripedThreadPoolExecutor callbackExecSvc,
GridAbsClosure errHnd)
throws IgniteCheckedException
{
@@ -771,6 +773,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
mgmtExecSvc,
igfsExecSvc,
restExecSvc,
+ callbackExecSvc,
plugins);
cfg.getMarshaller().setContext(ctx.marshallerContext());
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
index 9a83826..f47b7ff 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
@@ -95,6 +95,7 @@ import org.apache.ignite.spi.indexing.noop.NoopIndexingSpi;
import org.apache.ignite.spi.loadbalancing.roundrobin.RoundRobinLoadBalancingSpi;
import org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi;
import org.apache.ignite.spi.swapspace.noop.NoopSwapSpaceSpi;
+import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor;
import org.apache.ignite.thread.IgniteThread;
import org.apache.ignite.thread.IgniteThreadPoolExecutor;
import org.jetbrains.annotations.Nullable;
@@ -1473,6 +1474,9 @@ public class IgnitionEx {
/** Marshaller cache executor service. */
private ExecutorService marshCacheExecSvc;
+ /** Continuous query executor service. */
+ private IgniteStripedThreadPoolExecutor callbackExecSvc;
+
/** Grid state. */
private volatile IgniteState state = STOPPED;
@@ -1685,6 +1689,12 @@ public class IgnitionEx {
0,
new LinkedBlockingQueue<Runnable>());
+ // Note that we do not pre-start threads here as this pool may not be needed.
+ callbackExecSvc = new IgniteStripedThreadPoolExecutor(
+ cfg.getAsyncCallbackPoolSize(),
+ cfg.getGridName(),
+ "callback");
+
if (myCfg.getConnectorConfiguration() != null) {
restExecSvc = new IgniteThreadPoolExecutor(
"rest",
@@ -1724,7 +1734,7 @@ public class IgnitionEx {
grid = grid0;
grid0.start(myCfg, utilityCacheExecSvc, marshCacheExecSvc, execSvc, sysExecSvc, p2pExecSvc, mgmtExecSvc,
- igfsExecSvc, restExecSvc,
+ igfsExecSvc, restExecSvc, callbackExecSvc,
new CA() {
@Override public void apply() {
startLatch.countDown();
@@ -2327,6 +2337,10 @@ public class IgnitionEx {
U.shutdownNow(getClass(), marshCacheExecSvc, log);
marshCacheExecSvc = null;
+
+ U.shutdownNow(getClass(), callbackExecSvc, log);
+
+ callbackExecSvc = null;
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
index d6d7335..e679dfd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
@@ -27,6 +27,7 @@ import org.apache.ignite.cache.eviction.EvictableEntry;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.distributed.GridDistributedLockCancelledException;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
+import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateFuture;
import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -462,6 +463,7 @@ public interface GridCacheEntryEx {
* @param subjId Subject ID initiated this update.
* @param taskName Task name.
* @param updateCntr Update counter.
+ * @param fut Dht atomic future.
* @return Tuple where first value is flag showing whether operation succeeded,
* second value is old entry value if return value is requested, third is updated entry value,
* fourth is the version to enqueue for deferred delete the fifth is DR conflict context
@@ -497,7 +499,8 @@ public interface GridCacheEntryEx {
@Nullable UUID subjId,
String taskName,
@Nullable CacheObject prevVal,
- @Nullable Long updateCntr
+ @Nullable Long updateCntr,
+ @Nullable GridDhtAtomicUpdateFuture fut
) throws IgniteCheckedException, GridCacheEntryRemovedException;
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index 735e20a..75d96d8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
@@ -40,6 +40,7 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentInfoBean;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
+import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateFuture;
import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry;
import org.apache.ignite.internal.processors.cache.extras.GridCacheEntryExtras;
import org.apache.ignite.internal.processors.cache.extras.GridCacheMvccEntryExtras;
@@ -1248,6 +1249,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
tx.local(),
false,
updateCntr0,
+ null,
topVer);
}
@@ -1445,6 +1447,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
tx.local(),
false,
updateCntr0,
+ null,
topVer);
}
@@ -1821,6 +1824,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
true,
false,
updateCntr,
+ null,
AffinityTopologyVersion.NONE);
}
@@ -1870,7 +1874,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
@Nullable final UUID subjId,
final String taskName,
@Nullable final CacheObject prevVal,
- @Nullable final Long updateCntr
+ @Nullable final Long updateCntr,
+ @Nullable GridDhtAtomicUpdateFuture fut
) throws IgniteCheckedException, GridCacheEntryRemovedException, GridClosureException {
assert cctx.atomic();
@@ -1899,7 +1904,12 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
Long updateCntr0 = null;
synchronized (this) {
- boolean needVal = intercept || retval || op == GridCacheOperation.TRANSFORM || !F.isEmptyOrNulls(filter);
+ boolean internal = isInternal() || !context().userCache();
+
+ Map<UUID, CacheContinuousQueryListener> lsnrs = cctx.continuousQueries().updateListeners(internal, false);
+
+ boolean needVal = lsnrs != null || intercept || retval || op == GridCacheOperation.TRANSFORM
+ || !F.isEmptyOrNulls(filter);
checkObsolete();
@@ -2093,6 +2103,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
primary,
false,
updateCntr0,
+ null,
topVer);
}
@@ -2501,13 +2512,42 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
if (res)
updateMetrics(op, metrics);
+ // Continuous query filter should be perform under lock.
+ if (lsnrs != null) {
+ CacheObject evtVal = updated;
+ CacheObject evtOldVal = oldVal;
+
+ if (isOffHeapValuesOnly()) {
+ evtVal = cctx.toCacheObject(cctx.unwrapTemporary(evtVal));
+
+ evtOldVal = cctx.toCacheObject(cctx.unwrapTemporary(evtOldVal));
+ }
+
+ cctx.continuousQueries().onEntryUpdated(lsnrs, key, evtVal, evtOldVal, internal,
+ partition(), primary, false, updateCntr0, fut, topVer);
+ }
+
cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE, keepBinary);
if (intercept) {
if (op == GridCacheOperation.UPDATE)
- cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(cctx, key, key0, updated, updated0, keepBinary, updateCntr0));
+ cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(
+ cctx,
+ key,
+ key0,
+ updated,
+ updated0,
+ keepBinary,
+ updateCntr0));
else
- cctx.config().getInterceptor().onAfterRemove(new CacheLazyEntry(cctx, key, key0, oldVal, old0, keepBinary, updateCntr0));
+ cctx.config().getInterceptor().onAfterRemove(new CacheLazyEntry(
+ cctx,
+ key,
+ key0,
+ oldVal,
+ old0,
+ keepBinary,
+ updateCntr0));
if (interceptRes != null)
oldVal = cctx.toCacheObject(cctx.unwrapTemporary(interceptRes.get2()));
@@ -3302,6 +3342,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
true,
preload,
updateCntr,
+ null,
topVer);
cctx.dataStructures().onEntryUpdated(key, false, true);
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index 013184b..d28aaaa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@ -76,7 +76,6 @@ import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSing
import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
import org.apache.ignite.internal.processors.cache.dr.GridCacheDrExpirationInfo;
import org.apache.ignite.internal.processors.cache.dr.GridCacheDrInfo;
-import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener;
import org.apache.ignite.internal.processors.cache.transactions.IgniteTxLocalEx;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext;
@@ -2141,10 +2140,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
boolean intercept = ctx.config().getInterceptor() != null;
- boolean initLsnrs = false;
- Map<UUID, CacheContinuousQueryListener> lsnrs = null;
- boolean internal = false;
-
// Avoid iterator creation.
for (int i = 0; i < keys.size(); i++) {
KeyCacheObject k = keys.get(i);
@@ -2159,14 +2154,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
if (entry == null)
continue;
- if (!initLsnrs) {
- internal = entry.isInternal() || !context().userCache();
-
- lsnrs = ctx.continuousQueries().updateListeners(internal, false);
-
- initLsnrs = true;
- }
-
GridCacheVersion newConflictVer = req.conflictVersion(i);
long newConflictTtl = req.conflictTtl(i);
long newConflictExpireTime = req.conflictExpireTime(i);
@@ -2195,7 +2182,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
req.invokeArguments(),
primary && writeThrough() && !req.skipStore(),
!req.skipStore(),
- lsnrs != null || sndPrevVal || req.returnValue(),
+ sndPrevVal || req.returnValue(),
req.keepBinary(),
expiry,
true,
@@ -2213,7 +2200,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
req.subjectId(),
taskName,
null,
- null);
+ null,
+ dhtFut);
if (dhtFut == null && !F.isEmpty(filteredReaders)) {
dhtFut = createDhtFuture(ver, req, res, completionCb, true);
@@ -2222,8 +2210,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
}
if (dhtFut != null) {
- dhtFut.listeners(lsnrs);
-
if (updRes.sendToDht()) { // Send to backups even in case of remove-remove scenarios.
GridCacheVersionConflictContext<?, ?> conflictCtx = updRes.conflictResolveResult();
@@ -2260,19 +2246,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
"[entry=" + entry + ", filter=" + Arrays.toString(req.filter()) + ']');
}
}
- else if (lsnrs != null && updRes.updateCounter() != 0) {
- ctx.continuousQueries().onEntryUpdated(
- lsnrs,
- entry.key(),
- updRes.newValue(),
- updRes.oldValue(),
- internal,
- entry.partition(),
- primary,
- false,
- updRes.updateCounter(),
- topVer);
- }
if (hasNear) {
if (primary && updRes.sendToDht()) {
@@ -2446,9 +2419,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
boolean intercept = ctx.config().getInterceptor() != null;
- boolean initLsnrs = false;
- Map<UUID, CacheContinuousQueryListener> lsnrs = null;
-
// Avoid iterator creation.
for (int i = 0; i < entries.size(); i++) {
GridDhtCacheEntry entry = entries.get(i);
@@ -2482,14 +2452,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
filteredReaders = F.view(entry.readers(), F.notEqualTo(node.id()));
}
- if (!initLsnrs) {
- lsnrs = ctx.continuousQueries().updateListeners(
- entry.isInternal() || !context().userCache(),
- false);
-
- initLsnrs = true;
- }
-
GridCacheUpdateAtomicResult updRes = entry.innerUpdate(
ver,
node.id(),
@@ -2499,7 +2461,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
null,
/*write-through*/false,
/*read-through*/false,
- /*retval*/sndPrevVal || lsnrs != null,
+ /*retval*/sndPrevVal,
req.keepBinary(),
expiry,
/*event*/true,
@@ -2517,7 +2479,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
req.subjectId(),
taskName,
null,
- null);
+ null,
+ dhtFut);
assert !updRes.success() || updRes.newTtl() == CU.TTL_NOT_CHANGED || expiry != null :
"success=" + updRes.success() + ", newTtl=" + updRes.newTtl() + ", expiry=" + expiry;
@@ -2548,12 +2511,10 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
}
if (dhtFut != null) {
- dhtFut.listeners(lsnrs);
-
EntryProcessor<Object, Object, Object> entryProcessor =
entryProcessorMap == null ? null : entryProcessorMap.get(entry.key());
- if (!batchRes.readersOnly())
+ if (!batchRes.readersOnly()) {
dhtFut.addWriteEntry(entry,
writeVal,
entryProcessor,
@@ -2563,6 +2524,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
sndPrevVal,
updRes.oldValue(),
updRes.updateCounter());
+ }
if (!F.isEmpty(filteredReaders))
dhtFut.addNearWriteEntries(filteredReaders,
@@ -2572,19 +2534,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
updRes.newTtl(),
CU.EXPIRE_TIME_CALCULATE);
}
- else if (lsnrs != null && updRes.updateCounter() != 0) {
- ctx.continuousQueries().onEntryUpdated(
- lsnrs,
- entry.key(),
- updRes.newValue(),
- updRes.oldValue(),
- entry.isInternal() || !context().userCache(),
- entry.partition(),
- primary,
- false,
- updRes.updateCounter(),
- topVer);
- }
if (hasNear) {
if (primary) {
@@ -2965,10 +2914,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
String taskName = ctx.kernalContext().task().resolveTaskName(req.taskNameHash());
- boolean initLsnrs = false;
- Map<UUID, CacheContinuousQueryListener> lsnrs = null;
- boolean internal = false;
-
for (int i = 0; i < req.size(); i++) {
KeyCacheObject key = req.key(i);
@@ -2991,14 +2936,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
long ttl = req.ttl(i);
long expireTime = req.conflictExpireTime(i);
- if (!initLsnrs) {
- internal = entry.isInternal() || !context().userCache();
-
- lsnrs = ctx.continuousQueries().updateListeners(internal, false);
-
- initLsnrs = true;
- }
-
GridCacheUpdateAtomicResult updRes = entry.innerUpdate(
ver,
nodeId,
@@ -3008,7 +2945,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
op == TRANSFORM ? req.invokeArguments() : null,
/*write-through*/false,
/*read-through*/false,
- /*retval*/lsnrs != null,
+ /*retval*/false,
req.keepBinary(),
/*expiry policy*/null,
/*event*/true,
@@ -3026,25 +2963,12 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
req.subjectId(),
taskName,
prevVal,
- updateIdx);
+ updateIdx,
+ null);
if (updRes.removeVersion() != null)
ctx.onDeferredDelete(entry, updRes.removeVersion());
- if (lsnrs != null && updRes.updateCounter() != 0) {
- ctx.continuousQueries().onEntryUpdated(
- lsnrs,
- entry.key(),
- updRes.newValue(),
- updRes.oldValue(),
- internal,
- entry.partition(),
- false,
- false,
- updRes.updateCounter(),
- req.topologyVersion());
- }
-
entry.onUnlock();
break; // While.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
index 4721d6e..5760596 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
@@ -37,11 +37,11 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry;
-import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.CI1;
import org.apache.ignite.internal.util.typedef.CI2;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
@@ -97,15 +97,15 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
/** Future keys. */
private final Collection<KeyCacheObject> keys;
+ /** Continuous query closures. */
+ private Collection<CI1<Boolean>> cntQryClsrs;
+
/** */
private final boolean waitForExchange;
/** Response count. */
private volatile int resCnt;
- /** */
- private Map<UUID, CacheContinuousQueryListener> lsnrs;
-
/**
* @param cctx Cache context.
* @param completionCb Callback to invoke when future is completed.
@@ -138,13 +138,6 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
waitForExchange = !(updateReq.topologyLocked() || (updateReq.fastMap() && !updateReq.clientRequest()));
}
- /**
- * @param lsnrs Continuous query listeners.
- */
- void listeners(@Nullable Map<UUID, CacheContinuousQueryListener> lsnrs) {
- this.lsnrs = lsnrs;
- }
-
/** {@inheritDoc} */
@Override public IgniteUuid futureId() {
return futVer.asGridUuid();
@@ -276,27 +269,7 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
addPrevVal,
entry.partition(),
prevVal,
- updateCntr,
- lsnrs != null);
- }
- else if (lsnrs != null && dhtNodes.size() == 1) {
- try {
- cctx.continuousQueries().onEntryUpdated(
- lsnrs,
- entry.key(),
- val,
- prevVal,
- entry.key().internal() || !cctx.userCache(),
- entry.partition(),
- true,
- false,
- updateCntr,
- updateReq.topologyVersion());
- }
- catch (IgniteCheckedException e) {
- U.warn(log, "Failed to send continuous query message. [key=" + entry.key() + ", newVal="
- + val + ", err=" + e + "]");
- }
+ updateCntr);
}
}
}
@@ -361,77 +334,33 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
}
}
+ /**
+ * @param clsr Continuous query closure.
+ */
+ public void addContinuousQueryClosure(CI1<Boolean> clsr){
+ assert !isDone() : this;
+
+ if (cntQryClsrs == null)
+ cntQryClsrs = new ArrayList<>(10);
+
+ cntQryClsrs.add(clsr);
+ }
+
/** {@inheritDoc} */
@Override public boolean onDone(@Nullable Void res, @Nullable Throwable err) {
if (super.onDone(res, err)) {
cctx.mvcc().removeAtomicFuture(version());
- if (err != null) {
- if (!mappings.isEmpty() && lsnrs != null) {
- Collection<KeyCacheObject> hndKeys = new ArrayList<>(keys.size());
-
- exit: for (GridDhtAtomicUpdateRequest req : mappings.values()) {
- for (int i = 0; i < req.size(); i++) {
- KeyCacheObject key = req.key(i);
-
- if (!hndKeys.contains(key)) {
- updateRes.addFailedKey(key, err);
+ boolean suc = err == null;
- cctx.continuousQueries().skipUpdateEvent(
- lsnrs,
- key,
- req.partitionId(i),
- req.updateCounter(i),
- updateReq.topologyVersion());
-
- hndKeys.add(key);
-
- if (hndKeys.size() == keys.size())
- break exit;
- }
- }
- }
- }
- else
- for (KeyCacheObject key : keys)
- updateRes.addFailedKey(key, err);
+ if (!suc) {
+ for (KeyCacheObject key : keys)
+ updateRes.addFailedKey(key, err);
}
- else {
- if (lsnrs != null) {
- Collection<KeyCacheObject> hndKeys = new ArrayList<>(keys.size());
-
- exit: for (GridDhtAtomicUpdateRequest req : mappings.values()) {
- for (int i = 0; i < req.size(); i++) {
- KeyCacheObject key = req.key(i);
-
- if (!hndKeys.contains(key)) {
- try {
- cctx.continuousQueries().onEntryUpdated(
- lsnrs,
- key,
- req.value(i),
- req.localPreviousValue(i),
- key.internal() || !cctx.userCache(),
- req.partitionId(i),
- true,
- false,
- req.updateCounter(i),
- updateReq.topologyVersion());
- }
- catch (IgniteCheckedException e) {
- U.warn(log, "Failed to send continuous query message. [key=" + key +
- ", newVal=" + req.value(i) +
- ", err=" + e + "]");
- }
-
- hndKeys.add(key);
-
- if (hndKeys.size() == keys.size())
- break exit;
- }
- }
- }
- }
+
+ if (cntQryClsrs != null) {
+ for (CI1<Boolean> clsr : cntQryClsrs)
+ clsr.apply(suc);
}
if (updateReq.writeSynchronizationMode() == FULL_SYNC)
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
index c8e33c2..b5e2835 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
@@ -155,10 +155,6 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
@GridDirectTransient
private List<Integer> partIds;
- /** */
- @GridDirectTransient
- private List<CacheObject> locPrevVals;
-
/** Keep binary flag. */
private boolean keepBinary;
@@ -242,7 +238,6 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
* @param partId Partition.
* @param prevVal Previous value.
* @param updateCntr Update counter.
- * @param storeLocPrevVal If {@code true} stores previous value.
*/
public void addWriteValue(KeyCacheObject key,
@Nullable CacheObject val,
@@ -253,19 +248,12 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
boolean addPrevVal,
int partId,
@Nullable CacheObject prevVal,
- @Nullable Long updateCntr,
- boolean storeLocPrevVal) {
+ @Nullable Long updateCntr
+ ) {
keys.add(key);
partIds.add(partId);
- if (storeLocPrevVal) {
- if (locPrevVals == null)
- locPrevVals = new ArrayList<>();
-
- locPrevVals.add(prevVal);
- }
-
if (forceTransformBackups) {
assert entryProcessor != null;
@@ -526,16 +514,6 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
/**
* @param idx Key index.
- * @return Value.
- */
- @Nullable public CacheObject localPreviousValue(int idx) {
- assert locPrevVals != null;
-
- return locPrevVals.get(idx);
- }
-
- /**
- * @param idx Key index.
* @return Entry processor.
*/
@Nullable public EntryProcessor<Object, Object, Object> entryProcessor(int idx) {
@@ -1069,13 +1047,6 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
private void cleanup() {
nearVals = null;
prevVals = null;
-
- // Do not keep values if they are not needed for continuous query notification.
- if (locPrevVals == null) {
- keys = null;
- vals = null;
- locPrevVals = null;
- }
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
index a7481d3..3e0e392 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
@@ -37,7 +37,6 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
import org.apache.ignite.internal.processors.cache.GridCacheOperation;
-import org.apache.ignite.internal.processors.cache.GridCacheReturn;
import org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicResult;
import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheAdapter;
@@ -271,6 +270,7 @@ public class GridNearAtomicCache<K, V> extends GridNearCacheAdapter<K, V> {
subjId,
taskName,
null,
+ null,
null);
if (updRes.removeVersion() != null)
@@ -372,6 +372,7 @@ public class GridNearAtomicCache<K, V> extends GridNearCacheAdapter<K, V> {
req.subjectId(),
taskName,
null,
+ null,
null);
if (updRes.removeVersion() != null)
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
index eab5dbd..db70e2e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
@@ -56,6 +56,13 @@ class CacheContinuousQueryEvent<K, V> extends CacheQueryEntryEvent<K, V> {
return e;
}
+ /**
+ * @return Partition ID.
+ */
+ public int partitionId() {
+ return e.partition();
+ }
+
/** {@inheritDoc} */
@Override public K getKey() {
return (K)cctx.cacheObjectContext().unwrapBinaryIfNeeded(e.key(), e.isKeepBinary(), false);
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
index 16513b0..9ae2972 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
@@ -48,6 +48,7 @@ import org.apache.ignite.events.CacheQueryExecutedEvent;
import org.apache.ignite.events.CacheQueryReadEvent;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteDeploymentCheckedException;
+import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
import org.apache.ignite.internal.managers.communication.GridIoPolicy;
import org.apache.ignite.internal.managers.deployment.GridDeployment;
@@ -58,7 +59,10 @@ import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
import org.apache.ignite.internal.processors.cache.GridCacheAffinityManager;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager;
+import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateFuture;
import org.apache.ignite.internal.processors.cache.query.CacheQueryType;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryManager.JCacheQueryLocalListener;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryManager.JCacheQueryRemoteFilter;
import org.apache.ignite.internal.processors.continuous.GridContinuousBatch;
import org.apache.ignite.internal.processors.continuous.GridContinuousBatchAdapter;
import org.apache.ignite.internal.processors.continuous.GridContinuousHandler;
@@ -66,13 +70,14 @@ import org.apache.ignite.internal.processors.platform.cache.query.PlatformContin
import org.apache.ignite.internal.util.GridConcurrentSkipListSet;
import org.apache.ignite.internal.util.GridLongList;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
-import org.apache.ignite.internal.util.typedef.C1;
+import org.apache.ignite.internal.util.typedef.CI1;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteAsyncCallback;
import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.thread.IgniteStripedThreadPoolExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentLinkedDeque8;
@@ -159,6 +164,21 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
/** */
private transient boolean ignoreClsNotFound;
+ /** */
+ private transient boolean asyncCallback;
+
+ /** */
+ private transient UUID nodeId;
+
+ /** */
+ private transient UUID routineId;
+
+ /** */
+ private transient GridKernalContext ctx;
+
+ /** */
+ private transient IgniteLogger log;
+
/**
* Required by {@link Externalizable}.
*/
@@ -283,13 +303,36 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
assert routineId != null;
assert ctx != null;
- if (locLsnr != null)
- ctx.resource().injectGeneric(locLsnr);
+ if (locLsnr != null) {
+ if (locLsnr instanceof JCacheQueryLocalListener) {
+ ctx.resource().injectGeneric(((JCacheQueryLocalListener)locLsnr).impl);
+
+ asyncCallback = ((JCacheQueryLocalListener)locLsnr).async();
+ }
+ else {
+ ctx.resource().injectGeneric(locLsnr);
+
+ asyncCallback = U.hasAnnotation(locLsnr, IgniteAsyncCallback.class);
+ }
+ }
final CacheEntryEventFilter filter = getEventFilter();
- if (filter != null)
- ctx.resource().injectGeneric(filter);
+ if (filter != null) {
+ if (filter instanceof JCacheQueryRemoteFilter) {
+ if (((JCacheQueryRemoteFilter)filter).impl != null)
+ ctx.resource().injectGeneric(((JCacheQueryRemoteFilter)filter).impl);
+
+ if (!asyncCallback)
+ asyncCallback = ((JCacheQueryRemoteFilter)filter).async();
+ }
+ else {
+ ctx.resource().injectGeneric(filter);
+
+ if (!asyncCallback)
+ asyncCallback = U.hasAnnotation(filter, IgniteAsyncCallback.class);
+ }
+ }
entryBufs = new ConcurrentHashMap<>();
@@ -299,10 +342,18 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
rcvs = new ConcurrentHashMap<>();
+ this.nodeId = nodeId;
+
+ this.routineId = routineId;
+
+ this.ctx = ctx;
+
final boolean loc = nodeId.equals(ctx.localNodeId());
assert !skipPrimaryCheck || loc;
+ log = ctx.log(CacheContinuousQueryHandler.class);
+
CacheContinuousQueryListener<K, V> lsnr = new CacheContinuousQueryListener<K, V>() {
@Override public void onExecution() {
if (ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
@@ -324,15 +375,16 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
}
}
- /** {@inheritDoc} */
@Override public boolean keepBinary() {
return keepBinary;
}
- @Override public void onEntryUpdated(CacheContinuousQueryEvent<K, V> evt, boolean primary,
- boolean recordIgniteEvt) {
+ @Override public void onEntryUpdated(final CacheContinuousQueryEvent<K, V> evt,
+ boolean primary,
+ final boolean recordIgniteEvt,
+ GridDhtAtomicUpdateFuture fut) {
if (ignoreExpired && evt.getEventType() == EventType.EXPIRED)
- return;
+ return ;
final GridCacheContext<K, V> cctx = cacheContext(ctx);
@@ -343,93 +395,33 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
// skipPrimaryCheck is set only when listen locally for replicated cache events.
assert !skipPrimaryCheck || (cctx.isReplicated() && ctx.localNodeId().equals(nodeId));
- boolean notify = !evt.entry().isFiltered();
+ if (asyncCallback) {
+ ContinuousQueryAsyncClosure clsr = new ContinuousQueryAsyncClosure(
+ primary,
+ evt,
+ recordIgniteEvt,
+ fut);
- if (notify && filter != null) {
- try {
- notify = filter.evaluate(evt);
- }
- catch (Exception e) {
- U.error(cctx.logger(CacheContinuousQueryHandler.class), "CacheEntryEventFilter failed: " + e);
- }
+ ctx.asyncCallbackPool().execute(clsr, evt.partitionId());
}
-
- try {
- final CacheContinuousQueryEntry entry = evt.entry();
-
- if (!notify)
- entry.markFiltered();
+ else {
+ final boolean notify = filter(evt, primary);
if (primary || skipPrimaryCheck) {
- if (loc) {
- if (!locCache) {
- Collection<CacheEntryEvent<? extends K, ? extends V>> entries = handleEvent(ctx, entry);
-
- if (!entries.isEmpty()) {
- locLsnr.onUpdated(entries);
-
- if (!internal && !skipPrimaryCheck)
- sendBackupAcknowledge(ackBuf.onAcknowledged(entry), routineId, ctx);
- }
- }
- else {
- if (!entry.isFiltered())
- locLsnr.onUpdated(F.<CacheEntryEvent<? extends K, ? extends V>>asList(evt));
- }
- }
+ if (fut == null)
+ onEntryUpdate(evt, notify, loc, recordIgniteEvt);
else {
- if (!entry.isFiltered())
- prepareEntry(cctx, nodeId, entry);
-
- CacheContinuousQueryEntry e = handleEntry(entry);
-
- if (e != null)
- ctx.continuous().addNotification(nodeId, routineId, entry, topic, sync, true);
- }
- }
- else {
- if (!internal) {
- // Skip init query and expire entries.
- if (entry.updateCounter() != -1L) {
- entry.markBackup();
+ fut.addContinuousQueryClosure(new CI1<Boolean>() {
+ @Override public void apply(Boolean suc) {
+ if (!suc)
+ evt.entry().markFiltered();
- backupQueue.add(entry);
- }
+ onEntryUpdate(evt, notify, loc, recordIgniteEvt);
+ }
+ });
}
}
}
- catch (ClusterTopologyCheckedException ex) {
- IgniteLogger log = ctx.log(getClass());
-
- if (log.isDebugEnabled())
- log.debug("Failed to send event notification to node, node left cluster " +
- "[node=" + nodeId + ", err=" + ex + ']');
- }
- catch (IgniteCheckedException ex) {
- U.error(ctx.log(getClass()), "Failed to send event notification to node: " + nodeId, ex);
- }
-
- if (recordIgniteEvt && notify) {
- ctx.event().record(new CacheQueryReadEvent<>(
- ctx.discovery().localNode(),
- "Continuous query executed.",
- EVT_CACHE_QUERY_OBJECT_READ,
- CacheQueryType.CONTINUOUS.name(),
- cacheName,
- null,
- null,
- null,
- filter instanceof CacheEntryEventSerializableFilter ?
- (CacheEntryEventSerializableFilter)filter : null,
- null,
- nodeId,
- taskName(),
- evt.getKey(),
- evt.getValue(),
- evt.getOldValue(),
- null
- ));
- }
}
@Override public void onUnregister() {
@@ -475,15 +467,15 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
sendBackupAcknowledge(ackBuf.acknowledgeOnTimeout(), routineId, ctx);
}
- @Override public void skipUpdateEvent(CacheContinuousQueryEvent<K, V> evt, AffinityTopologyVersion topVer,
- boolean primary) {
+ @Override public void skipUpdateEvent(CacheContinuousQueryEvent<K, V> evt,
+ AffinityTopologyVersion topVer, boolean primary) {
assert evt != null;
CacheContinuousQueryEntry e = evt.entry();
e.markFiltered();
- onEntryUpdated(evt, primary, false);
+ onEntryUpdated(evt, primary, false, null);
}
@Override public void onPartitionEvicted(int part) {
@@ -580,17 +572,73 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
- @Override public void notifyCallback(UUID nodeId, UUID routineId, Collection<?> objs, GridKernalContext ctx) {
+ @Override public void notifyCallback(final UUID nodeId,
+ final UUID routineId,
+ Collection<?> objs,
+ final GridKernalContext ctx) {
assert nodeId != null;
assert routineId != null;
assert objs != null;
assert ctx != null;
- Collection<CacheContinuousQueryEntry> entries = (Collection<CacheContinuousQueryEntry>)objs;
+ final List<CacheContinuousQueryEntry> entries = (List<CacheContinuousQueryEntry>)objs;
+
+ if (entries.isEmpty())
+ return;
+
+ if (asyncCallback) {
+ IgniteStripedThreadPoolExecutor asyncPool = ctx.asyncCallbackPool();
+
+ int threadId = asyncPool.threadId(entries.get(0).partition());
+
+ int startIdx = 0;
+
+ if (entries.size() != 1) {
+ for (int i = 1; i < entries.size(); i++) {
+ int curThreadId = asyncPool.threadId(entries.get(i).partition());
+
+ // If all entries from one partition avoid creation new collections.
+ if (curThreadId == threadId)
+ continue;
+
+ final int i0 = i;
+ final int startIdx0 = startIdx;
+
+ asyncPool.execute(new Runnable() {
+ @Override public void run() {
+ notifyCallback0(nodeId, ctx, entries.subList(startIdx0, i0));
+ }
+ }, threadId);
+
+ startIdx = i0;
+ threadId = curThreadId;
+ }
+ }
+
+ final int startIdx0 = startIdx;
+
+ asyncPool.execute(new Runnable() {
+ @Override public void run() {
+ notifyCallback0(nodeId, ctx,
+ startIdx0 == 0 ? entries : entries.subList(startIdx0, entries.size()));
+ }
+ }, threadId);
+ }
+ else
+ notifyCallback0(nodeId, ctx, entries);
+ }
+ /**
+ * @param nodeId Node id.
+ * @param ctx Kernal context.
+ * @param entries Entries.
+ */
+ private void notifyCallback0(UUID nodeId,
+ final GridKernalContext ctx,
+ Collection<CacheContinuousQueryEntry> entries) {
final GridCacheContext cctx = cacheContext(ctx);
- Collection<CacheEntryEvent<? extends K, ? extends V>> entries0 = new ArrayList<>();
+ final Collection<CacheEntryEvent<? extends K, ? extends V>> entries0 = new ArrayList<>(entries.size());
for (CacheContinuousQueryEntry e : entries) {
GridCacheDeploymentManager depMgr = cctx.deploy();
@@ -609,7 +657,10 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
try {
e.unmarshal(cctx, ldr);
- entries0.addAll(handleEvent(ctx, e));
+ Collection<CacheEntryEvent<? extends K, ? extends V>> evts = handleEvent(ctx, e);
+
+ if (evts != null && !evts.isEmpty())
+ entries0.addAll(evts);
}
catch (IgniteCheckedException ex) {
if (ignoreClsNotFound)
@@ -640,8 +691,8 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
if (e.isFiltered())
return Collections.emptyList();
else
- return F.<CacheEntryEvent<? extends K, ? extends V>>asList(
- new CacheContinuousQueryEvent<K, V>(cache, cctx, e));
+ return F.<CacheEntryEvent<? extends K, ? extends V>>
+ asList(new CacheContinuousQueryEvent<K, V>(cache, cctx, e));
}
// Initial query entry or evicted entry. These events should be fired immediately.
@@ -653,7 +704,117 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
PartitionRecovery rec = getOrCreatePartitionRecovery(ctx, e.partition());
- return rec.collectEntries(cctx, cache, e);
+ return rec.collectEntries(e, cctx, cache);
+ }
+
+ /**
+ * @param primary Primary.
+ * @param evt Query event.
+ * @return {@code True} if event passed filter otherwise {@code true}.
+ */
+ public boolean filter(CacheContinuousQueryEvent evt, boolean primary) {
+ CacheContinuousQueryEntry entry = evt.entry();
+
+ boolean notify = !entry.isFiltered();
+
+ try {
+ if (notify && getEventFilter() != null)
+ notify = getEventFilter().evaluate(evt);
+ }
+ catch (Exception e) {
+ U.error(log, "CacheEntryEventFilter failed: " + e);
+ }
+
+ if (!notify)
+ entry.markFiltered();
+
+ if (!primary && !internal && entry.updateCounter() != -1L /* Skip init query and expire entries */) {
+ entry.markBackup();
+
+ backupQueue.add(entry);
+ }
+
+ return notify;
+ }
+
+ /**
+ * @param evt Continuous query event.
+ * @param notify Notify flag.
+ * @param loc Listener deployed on this node.
+ * @param recordIgniteEvt Record ignite event.
+ */
+ private void onEntryUpdate(CacheContinuousQueryEvent evt, boolean notify, boolean loc, boolean recordIgniteEvt) {
+ try {
+ GridCacheContext<K, V> cctx = cacheContext(ctx);
+
+ if (cctx == null)
+ return;
+
+ final CacheContinuousQueryEntry entry = evt.entry();
+
+ if (loc) {
+ if (!locCache) {
+ Collection<CacheEntryEvent<? extends K, ? extends V>> evts = handleEvent(ctx, entry);
+
+ if (!evts.isEmpty()) {
+ locLsnr.onUpdated(evts);
+
+ if (!internal && !skipPrimaryCheck)
+ sendBackupAcknowledge(ackBuf.onAcknowledged(entry), routineId, ctx);
+ }
+ }
+ else {
+ if (!entry.isFiltered())
+ locLsnr.onUpdated(F.<CacheEntryEvent<? extends K, ? extends V>>asList(evt));
+ }
+ }
+ else {
+ if (!entry.isFiltered())
+ prepareEntry(cctx, nodeId, entry);
+
+ CacheContinuousQueryEntry e = handleEntry(entry);
+
+ if (e != null)
+ ctx.continuous().addNotification(nodeId, routineId, entry, topic, sync, true);
+ }
+ }
+ catch (ClusterTopologyCheckedException ex) {
+ if (log.isDebugEnabled())
+ log.debug("Failed to send event notification to node, node left cluster " +
+ "[node=" + nodeId + ", err=" + ex + ']');
+ }
+ catch (IgniteCheckedException ex) {
+ U.error(ctx.log(getClass()), "Failed to send event notification to node: " + nodeId, ex);
+ }
+
+ if (recordIgniteEvt && notify) {
+ ctx.event().record(new CacheQueryReadEvent<>(
+ ctx.discovery().localNode(),
+ "Continuous query executed.",
+ EVT_CACHE_QUERY_OBJECT_READ,
+ CacheQueryType.CONTINUOUS.name(),
+ cacheName,
+ null,
+ null,
+ null,
+ getEventFilter() instanceof CacheEntryEventSerializableFilter ?
+ (CacheEntryEventSerializableFilter)getEventFilter() : null,
+ null,
+ nodeId,
+ taskName(),
+ evt.getKey(),
+ evt.getValue(),
+ evt.getOldValue(),
+ null
+ ));
+ }
+ }
+
+ /**
+ * @return Task name.
+ */
+ private String taskName() {
+ return ctx.security().enabled() ? ctx.task().resolveTaskName(taskHash) : null;
}
/**
@@ -781,9 +942,11 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
* @param entry Cache continuous query entry.
* @return Collection entries which will be fired. This collection should contains only non-filtered events.
*/
- public <K, V> Collection<CacheEntryEvent<? extends K, ? extends V>> collectEntries(GridCacheContext cctx,
- IgniteCache cache,
- CacheContinuousQueryEntry entry) {
+ <K, V> Collection<CacheEntryEvent<? extends K, ? extends V>> collectEntries(
+ CacheContinuousQueryEntry entry,
+ GridCacheContext cctx,
+ IgniteCache cache
+ ) {
assert entry != null;
if (entry.topologyVersion() == null) { // Possible if entry is sent from old node.
@@ -1241,6 +1404,87 @@ public class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler
}
/**
+ *
+ */
+ private class ContinuousQueryAsyncClosure implements Runnable {
+ /** */
+ private final CacheContinuousQueryEvent<K, V> evt;
+
+ /** */
+ private final boolean primary;
+
+ /** */
+ private final boolean recordIgniteEvt;
+
+ /** */
+ private final IgniteInternalFuture<?> fut;
+
+ /**
+ * @param primary Primary flag.
+ * @param evt Event.
+ * @param recordIgniteEvt Fired event.
+ * @param fut Dht future.
+ */
+ ContinuousQueryAsyncClosure(
+ boolean primary,
+ CacheContinuousQueryEvent<K, V> evt,
+ boolean recordIgniteEvt,
+ IgniteInternalFuture<?> fut) {
+ this.primary = primary;
+ this.evt = evt;
+ this.recordIgniteEvt = recordIgniteEvt;
+ this.fut = fut;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void run() {
+ final boolean notify = filter(evt, primary);
+
+ if (!primary())
+ return;
+
+ if (fut == null) {
+ onEntryUpdate(evt, notify, nodeId.equals(ctx.localNodeId()), recordIgniteEvt);
+
+ return;
+ }
+
+ if (fut.isDone()) {
+ if (fut.error() != null)
+ evt.entry().markFiltered();
+
+ onEntryUpdate(evt, notify, nodeId.equals(ctx.localNodeId()), recordIgniteEvt);
+ }
+ else {
+ fut.listen(new CI1<IgniteInternalFuture<?>>() {
+ @Override public void apply(IgniteInternalFuture<?> f) {
+ if (f.error() != null)
+ evt.entry().markFiltered();
+
+ ctx.asyncCallbackPool().execute(new Runnable() {
+ @Override public void run() {
+ onEntryUpdate(evt, notify, nodeId.equals(ctx.localNodeId()), recordIgniteEvt);
+ }
+ }, evt.entry().partition());
+ }
+ });
+ }
+ }
+
+ /**
+ * @return {@code True} if event fired on this node.
+ */
+ private boolean primary() {
+ return primary || skipPrimaryCheck;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return S.toString(ContinuousQueryAsyncClosure.class, this);
+ }
+ }
+
+ /**
* Deployable object.
*/
protected static class DeployableObject implements Externalizable {
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ff64c2a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
index 83ff32c..8eca81c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
@@ -20,6 +20,8 @@ package org.apache.ignite.internal.processors.cache.query.continuous;
import java.util.Map;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateFuture;
+import org.jetbrains.annotations.Nullable;
/**
* Continuous query listener.
@@ -36,8 +38,10 @@ public interface CacheContinuousQueryListener<K, V> {
* @param evt Event
* @param primary Primary flag.
* @param recordIgniteEvt Whether to record event.
+ * @param fut Dht atomic future.
*/
- public void onEntryUpdated(CacheContinuousQueryEvent<K, V> evt, boolean primary, boolean recordIgniteEvt);
+ public void onEntryUpdated(CacheContinuousQueryEvent<K, V> evt, boolean primary,
+ boolean recordIgniteEvt, @Nullable GridDhtAtomicUpdateFuture fut);
/**
* Listener unregistered callback.