From 3a456d45de843c2cde9cd8f74368fea3dbd0197f Mon Sep 17 00:00:00 2001 From: Abinasha Karana Date: Thu, 28 Mar 2013 13:38:07 +0530 Subject: [PATCH] hsearch federated 1.2 version upgrade with bug Fixes. Partition index hits only a specific column as required when the value is exact. Lots of test cases to ensure the federated search is proper. --- .classpath | 106 +++++- build.properties | 2 +- .../hsearch/treetable/compiler/schema.txt | 21 +- .../hsearch/treetable/storage/examresult.json | 47 +++ hsearch-core.jar | Bin 342915 -> 343355 bytes lib/hsearch-federated.jar | Bin 22995 -> 0 bytes lib/hsearch-federated_1.2.jar | Bin 0 -> 22779 bytes lib/src-hsearch-federated.jar | Bin 7398 -> 0 bytes lib/src-hsearch-federated_1.2.jar | Bin 0 -> 7296 bytes logs/perf.xml | 0 src-hsearch-core.jar | Bin 173963 -> 174115 bytes .../com/bizosys/hsearch/treetable/Cell2.java | 22 ++ .../client/HSearchProcessingInstruction.java | 1 + .../client/partition/PartitionNumeric.java | 18 +- .../hsearch/treetable/compiler/schema.txt | 21 +- .../treetable/storage/HSearchTableReader.java | 3 +- .../bizosys/hsearch/treetable/Cell2Test.java | 22 +- .../treetable/storage/DataCreator.java | 79 ++++ .../treetable/storage/SearchTester.java | 346 ++++++++++++++++++ .../hsearch/treetable/storage/examresult.json | 47 +++ .../treetable/storage/sampleImpl/Client.java | 73 ++++ .../treetable/storage/sampleImpl/Filter.java | 47 +++ .../storage/sampleImpl/MapperExamResult.java | 180 +++++++++ .../treetable/storage/sampleImpl/Reducer.java | 35 ++ .../donotmodify/HBaseTableSchema.java | 46 +++ .../donotmodify/HSearchTableCombinerImpl.java | 19 + .../donotmodify/HSearchTableExamResult.java | 345 +++++++++++++++++ .../HSearchTableMultiQueryProcessorImpl.java | 17 + .../donotmodify/PluginExamResultBase.java | 21 ++ 29 files changed, 1475 insertions(+), 43 deletions(-) create mode 100644 classes/com/bizosys/hsearch/treetable/storage/examresult.json delete mode 100644 lib/hsearch-federated.jar create mode 100644 lib/hsearch-federated_1.2.jar delete mode 100644 lib/src-hsearch-federated.jar create mode 100644 lib/src-hsearch-federated_1.2.jar create mode 100644 logs/perf.xml create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/DataCreator.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/SearchTester.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/examresult.json create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Client.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Filter.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/MapperExamResult.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Reducer.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HBaseTableSchema.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableCombinerImpl.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableExamResult.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableMultiQueryProcessorImpl.java create mode 100644 src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/PluginExamResultBase.java diff --git a/.classpath b/.classpath index da7555f..42849f8 100644 --- a/.classpath +++ b/.classpath @@ -11,12 +11,114 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.properties b/build.properties index 973aa53..a95fed5 100644 --- a/build.properties +++ b/build.properties @@ -1,5 +1,5 @@ name=hsearch-core -version=0.94.2.207 +version=0.94.2.208 company=Bizosys Technologies Pvt Ltd. diff --git a/classes/com/bizosys/hsearch/treetable/compiler/schema.txt b/classes/com/bizosys/hsearch/treetable/compiler/schema.txt index 0f27243..bff9db2 100644 --- a/classes/com/bizosys/hsearch/treetable/compiler/schema.txt +++ b/classes/com/bizosys/hsearch/treetable/compiler/schema.txt @@ -2,26 +2,15 @@ "module" : "com.delme.generated", "table": "htable", "columns": [ - { - "name": "Resumes", + { + "name": "ExamResult", "mergeId": { "name": "mergeId", "datatype": "Integer" }, - "indexes": "unstructured" - }, - - { - "name": "EmpDetail", - - "mergeId": { - "name": "mergeId", - "datatype": "Integer" - }, - - "indexes": [ + "indexes": [ { "name": "age", "datatype": "Integer" @@ -48,8 +37,8 @@ }, "partitions": { - "names": "a,b,c,d,e,f,g,h,i", - "ranges": "[*:-123],[-123:-11],[-11:23],[23:45],[45:134],[134:10012],[10012:213923],[213923:1111111],[1111111:*]", + "names": "a,b,c,d,e,f,g,h,i,j", + "ranges": "[0:10],[10:20],[20:30],[30:40],[40:50],[50:60],[60:70],[70:80],[80:90][90:100]", "column" : 4 , "type" : "numeric" } diff --git a/classes/com/bizosys/hsearch/treetable/storage/examresult.json b/classes/com/bizosys/hsearch/treetable/storage/examresult.json new file mode 100644 index 0000000..226f1aa --- /dev/null +++ b/classes/com/bizosys/hsearch/treetable/storage/examresult.json @@ -0,0 +1,47 @@ +{ + "module" : "com.bizosys.hsearch.treetable.storage.sampleImpl", + "table": "htable-test", + "columns": [ + { + "name": "ExamResult", + + "mergeId": { + "name": "mergeId", + "datatype": "Integer" + }, + + "indexes": [ + { + "name": "age", + "datatype": "Integer" + }, + { + "name": "role", + "datatype": "String" + }, + { + "name": "location", + "datatype": "String" + } + ], + + "key": { + "name": "empid", + "datatype": "Integer" + }, + + "value": + { + "name": "mark", + "datatype": "Float" + }, + + "partitions": { + "names": "a,b,c,d,e,f,g,h,i,j", + "ranges": "[*:1],[1:2],[2:3],[3:4],[4:5],[5:6],[6:7],[7:8],[8:9],[9:*]", + "column" : 4 , + "type" : "numeric" + } + } + ] +} \ No newline at end of file diff --git a/hsearch-core.jar b/hsearch-core.jar index b5d2b2fbc84bf8e235510d751b55ac8144d9b91c..e2ec66b42412b6fa942ef8b8eb32c7648365b1e1 100644 GIT binary patch delta 23550 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 L=@Rxgb}!-omE3oo delta 23343 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
    JuSz+%Se7av2xt1HB9XT%*v#L4_d?NTs$5| zZkQiuR_>_=zY_dm8o%%%#a}qt+Q-cwUs?42bnx@RAFlBOrYe5POuV^q zd7Y(RH7re}p-)%?WrkA0-Ve}swF-)R)*3(uip;@q|D>SjGWx_y=EqYDl;ybj{g@Yg z9W%$zSP%5N<~1nltV9t=0g0lonZ8$>c-m^nVKkP3erL>c!^mmpHrSl)5eiaF*AHUqsafU`Zv9%qE)kWWfRqtnhg*0#| z83wK#Wx)ut7hvXQ-K-Dyj&`Dv{(*uPY55F0rXr~A_&<@q^*b1Q=eT4vrl8nt%Y9C@ z=gaKzPOd^S9Ztb*h*c@rm~f)CDKKK3azSy@N>%QeSPO%H~^-$eccVefm5;+SYYBEj9)yh@QgE7FYTp_gLfZ~?YZytJtx)ptSsTItfSX3 zHmAb)x964dQ)wcEa8}lzMqI%3$h$h3mUg06OY71@2>Gj+j{Pe1+_`tUmTsD&;f z`>LG8)Er9ti_J%C2&hreK=@t#fMQGseS z(tFIo>W+62Xe$EM$N85TE~=e&=ZG-L54V-P)P`kpB^LDITC{ztm|s9?xh6FrcwAW% zlIrN&bNw4Sm#M{B8P(Hgb)T=e90O~X{`EaLu;DwG5t@U-C9E}8hVkaKxEDMSb|*d~ zHP$^(GOL7Ame~R+G9OO{TP-VFG~+0EpMpP5TL4{xLuutETlwQE1(grNH!3_lQwBl${BufrUxO{6 z*A$Vq%(HDN=Gm#(Y3hs5)-|jaPbG!IPSeR2tyXsK_xV>w9;rZJ=@`TkExX31Zc257 z@&3zv_t6$?=QaMQ4K98lIa+K9THo;llRX3}Jh4%yIjM07RwTwZGd^Imj@ugxM3jVM z@gI+QZ}f)kw6FlR=J4EyW_qS`@?Blgi_R9{iDM=0AdQxjXm=^832SB{VhBA>UHF$a z6^ck{;Nph-T?X3qV{B{FH3P#snOZ30k1K+1?SGW+f^Te*y$bX=GuE9^j1}M7LgXey aDj#Pk8hdYc?E5{Sq@lv$S@{#j&G;W;?SKdX diff --git a/lib/hsearch-federated.jar b/lib/hsearch-federated.jar deleted file mode 100644 index d5046d816e022bef66a5dfd1f1a13c4f9f8d6473..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22995 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 literal 0 HcmV?d00001 diff --git a/lib/src-hsearch-federated.jar b/lib/src-hsearch-federated.jar deleted file mode 100644 index 187b265a95345b275d2a8e410124b3472dcf76f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7398 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 a>o`;C{wn=_UG diff --git a/lib/src-hsearch-federated_1.2.jar b/lib/src-hsearch-federated_1.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..aaa6080ed14a4f5fe5fcd41915156de32fd79adc GIT binary patch literal 7296 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 literal 0 HcmV?d00001 diff --git a/logs/perf.xml b/logs/perf.xml new file mode 100644 index 0000000..e69de29 diff --git a/src-hsearch-core.jar b/src-hsearch-core.jar index 81ee936e833522ffd1befa09619c395add503d20..f69ed4caffb2d5b9998c294e5c1d3decd72fe56c 100644 GIT binary patch delta 8126 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 Gr~MyY)3@ya delta 7899 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 diff --git a/src/java/com/bizosys/hsearch/treetable/Cell2.java b/src/java/com/bizosys/hsearch/treetable/Cell2.java index 5755794..01bc587 100644 --- a/src/java/com/bizosys/hsearch/treetable/Cell2.java +++ b/src/java/com/bizosys/hsearch/treetable/Cell2.java @@ -168,6 +168,11 @@ public void getMap(V exactValue, V minimumValue, V maximumValue, public void populate(Map map) throws IOException { ISortedByte kvB = SortedBytesArray.getInstance().parse(data.data, data.offset, data.length); + if ( kvB.getSize() == 0 ) { + System.err.println("Null Values to pipulate in Cell2"); + return; + } + byte[] allKeysB = kvB.getValueAt(0); if ( null == allKeysB ) return; @@ -207,6 +212,23 @@ public byte[] toBytesOnSortedData() throws IOException { return cellB; } + public byte[] toBytesOnSortedData(Map customMap) throws IOException { + + if ( null == customMap) return null; + if ( customMap.size() == 0 ) return null; + + Collection keys = customMap.keySet(); + Collection values = customMap.values(); + + List bytesElems = new ArrayList(); + bytesElems.add(k1Sorter.toBytes(keys)); + bytesElems.add(vSorter.toBytes(values)); + + byte[] cellB = SortedBytesArray.getInstance().toBytes(bytesElems); + bytesElems.clear(); + return cellB; + } + public byte[] toBytes(V minValue, V maximumValue, boolean leftInclusize, boolean rightInclusize, Comparator vComp) throws IOException { if ( sortedList.size() == 0 ) return null; diff --git a/src/java/com/bizosys/hsearch/treetable/client/HSearchProcessingInstruction.java b/src/java/com/bizosys/hsearch/treetable/client/HSearchProcessingInstruction.java index 9e49ad5..5ddddf9 100644 --- a/src/java/com/bizosys/hsearch/treetable/client/HSearchProcessingInstruction.java +++ b/src/java/com/bizosys/hsearch/treetable/client/HSearchProcessingInstruction.java @@ -127,6 +127,7 @@ public static String ser(FunctionExpr[] functions) { public static void main(String[] args) throws ParseException { FunctionExpr count = new FunctionExpr(1, FunctionRepos.COUNT); FunctionExpr min = new FunctionExpr(21, FunctionRepos.COUNT); + HSearchProcessingInstruction o = new HSearchProcessingInstruction(PLUGIN_CALLBACK_COLS, OUTPUT_COLS, new FunctionExpr[]{count, min}); diff --git a/src/java/com/bizosys/hsearch/treetable/client/partition/PartitionNumeric.java b/src/java/com/bizosys/hsearch/treetable/client/partition/PartitionNumeric.java index 5a6f397..c7b844d 100644 --- a/src/java/com/bizosys/hsearch/treetable/client/partition/PartitionNumeric.java +++ b/src/java/com/bizosys/hsearch/treetable/client/partition/PartitionNumeric.java @@ -78,13 +78,12 @@ public void setPartitionsAndRange(String colName, String familyNames, String ran public void getMatchingFamilies(HSearchQuery query, Set uniqueFamilies) throws IOException { if ( query.filterCells[this.partitionIndex]) { - if ( null == query.exactValCellsO) { + if ( null == query.exactValCells[this.partitionIndex]) { double min = query.minValCells[this.partitionIndex]; double max = query.maxValCells[this.partitionIndex]; getColumnFamilies(min, max, uniqueFamilies); } else { - Object exact = query.exactValCellsO[this.partitionIndex]; - uniqueFamilies.add(getColumnFamily(new Double(exact.toString()) )); + uniqueFamilies.add(getColumnFamily(new Double(query.exactValCells[this.partitionIndex]) )); } } else { getColumnFamilies(HSearchQuery.DOUBLE_MIN_VALUE, HSearchQuery.DOUBLE_MAX_VALUE, uniqueFamilies); @@ -121,8 +120,13 @@ public void getColumnFamilies(Double startVal, Double endVal, Set famili } - if ( !isStart ) - throw new IOException("No matching columns found for value = " + startVal + ":" + endVal +"\n" + families.toString()); + if ( !isStart ) { + System.err.println("Start is not found. Adding All : " + startVal + "\t-\t" + endVal); + for (NumericRange aRange : rangeL) { + families.add(colName + "_" + aRange.ext); + } + } + //throw new IOException("No matching columns found for value = " + startVal + ":" + endVal +"\n" + families.toString()); } @@ -131,11 +135,15 @@ public String getColumnFamily(Double exactVal) throws IOException { if ( rangeL.size() == 0 ) return colName; + NumericRange lastRange = null; for (NumericRange aRange : rangeL) { if ( aRange.start <= exactVal && aRange.end > exactVal) return colName + "_" + aRange.ext; + lastRange = aRange; } + if ( lastRange.end == exactVal) return colName + "_" + lastRange.ext; + throw new IOException("No matching columns found for value :" + exactVal); } diff --git a/src/java/com/bizosys/hsearch/treetable/compiler/schema.txt b/src/java/com/bizosys/hsearch/treetable/compiler/schema.txt index 0f27243..bff9db2 100644 --- a/src/java/com/bizosys/hsearch/treetable/compiler/schema.txt +++ b/src/java/com/bizosys/hsearch/treetable/compiler/schema.txt @@ -2,26 +2,15 @@ "module" : "com.delme.generated", "table": "htable", "columns": [ - { - "name": "Resumes", + { + "name": "ExamResult", "mergeId": { "name": "mergeId", "datatype": "Integer" }, - "indexes": "unstructured" - }, - - { - "name": "EmpDetail", - - "mergeId": { - "name": "mergeId", - "datatype": "Integer" - }, - - "indexes": [ + "indexes": [ { "name": "age", "datatype": "Integer" @@ -48,8 +37,8 @@ }, "partitions": { - "names": "a,b,c,d,e,f,g,h,i", - "ranges": "[*:-123],[-123:-11],[-11:23],[23:45],[45:134],[134:10012],[10012:213923],[213923:1111111],[1111111:*]", + "names": "a,b,c,d,e,f,g,h,i,j", + "ranges": "[0:10],[10:20],[20:30],[30:40],[40:50],[50:60],[60:70],[70:80],[80:90][90:100]", "column" : 4 , "type" : "numeric" } diff --git a/src/java/com/bizosys/hsearch/treetable/storage/HSearchTableReader.java b/src/java/com/bizosys/hsearch/treetable/storage/HSearchTableReader.java index 736e6ce..2f29ab8 100644 --- a/src/java/com/bizosys/hsearch/treetable/storage/HSearchTableReader.java +++ b/src/java/com/bizosys/hsearch/treetable/storage/HSearchTableReader.java @@ -39,6 +39,7 @@ public abstract class HSearchTableReader implements IScanCallBack { public static boolean DEBUG_ENABLED = HbaseLog.l.isDebugEnabled(); + public static boolean INFO_ENABLED = HbaseLog.l.isInfoEnabled(); //public static ParallelHReader parallelReader = new ParallelHReader(10); @@ -91,7 +92,7 @@ public void read( String multiQuery, Map multiQueryParts, List families = new ArrayList(); for (String family : uniqueFamilies) { - if ( DEBUG_ENABLED ) HbaseLog.l.debug("HSearchTableReader > Adding Family: " + family); + if ( INFO_ENABLED ) HbaseLog.l.info("HSearchTableReader > Adding Family: " + family); families.add(new ColumnFamName(family.getBytes(), HBaseTableSchemaDefn.COL_NAME_BYTES)); } diff --git a/src/test/com/bizosys/hsearch/treetable/Cell2Test.java b/src/test/com/bizosys/hsearch/treetable/Cell2Test.java index 9423bc6..33e4f7a 100644 --- a/src/test/com/bizosys/hsearch/treetable/Cell2Test.java +++ b/src/test/com/bizosys/hsearch/treetable/Cell2Test.java @@ -26,7 +26,7 @@ public class Cell2Test extends TestCase { public static String[] modes = new String[] { "all", "random", "method"}; - public static String mode = modes[1]; + public static String mode = modes[2]; public static void main(String[] args) throws Exception { Cell2Test t = new Cell2Test(); @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { } else if ( modes[2].equals(mode) ) { t.setUp(); - t.testCallbackFiltering(); + t.toBytesOnSortedDataWithMapTest(); t.tearDown(); } } @@ -604,5 +604,23 @@ public void testBooleanBoolean() throws Exception { } } + public void toBytesOnSortedDataWithMapTest() throws Exception { + Map cellL = new HashMap(); + for ( int i=0; i< 100; i++) { + cellL.put("key" + i, "value" + i); + } + Cell2 cellMap = new Cell2( + SortedBytesString.getInstance(), SortedBytesString.getInstance() ); + byte[] ser = cellMap.toBytesOnSortedData(cellL); + + Map deserL = new HashMap(); + + new Cell2( + SortedBytesString.getInstance(), SortedBytesString.getInstance(), ser ). + populate(deserL); + System.out.println(deserL.toString()); + + } + } diff --git a/src/test/com/bizosys/hsearch/treetable/storage/DataCreator.java b/src/test/com/bizosys/hsearch/treetable/storage/DataCreator.java new file mode 100644 index 0000000..eca8556 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/DataCreator.java @@ -0,0 +1,79 @@ +package com.bizosys.hsearch.treetable.storage; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import com.bizosys.hsearch.hbase.HDML; +import com.bizosys.hsearch.hbase.HWriter; +import com.bizosys.hsearch.hbase.NV; +import com.bizosys.hsearch.hbase.RecordScalar; +import com.bizosys.hsearch.treetable.client.HSearchProcessingInstruction; +import com.bizosys.hsearch.treetable.client.partition.IPartition; +import com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify.*; + +public class DataCreator { + /** + * m|1|[1:7432]|[1:4]|*|[1:758320]|* + * Range Query - [1:7432] + * Match All - * + * Exact match - m + */ + + public static void main(String[] args) throws Exception { + + HBaseTableSchemaDefn schema = HBaseTableSchema.getInstance().getSchema(); + String colFamily = schema.columnPartions.keySet().iterator().next(); + + IPartition partition = schema.columnPartions.get(colFamily); + for ( String famExt : partition.getPartitionNames() ) { + System.out.println(famExt); + HDML.truncate(schema.tableName, new NV( + (schema.columnPartions.keySet().iterator().next() + "_" + famExt) .getBytes(), "1".getBytes() )); + } + + Map tableParts = new HashMap(); + + int [] ages = new int[] {22,23,24,25,26}; + int agesCounter = 0; + + String [] role = new String[] {"scout","monitor","captain","student"}; + int roleCounter = 0; + + for ( int i=0; i<101; i++) { + + HSearchTableExamResult part = null; + + String family = partition.getColumnFamily( (double) i/10); + if (tableParts.containsKey(family)) { + part = tableParts.get(family); + } else { + part = new HSearchTableExamResult(); + tableParts.put(family, part); + } + + part.put( ages[agesCounter], role[roleCounter], "classx", i, (float) i/10 ); + + agesCounter++; + if ( agesCounter > 4) agesCounter = 0; + + roleCounter++; + if ( roleCounter > 3) roleCounter = 0; + } + + + List records = new ArrayList(); + for (String family : tableParts.keySet()) { + System.out.println("Writting to Family :" + family); + records.add( new RecordScalar ( + "row1".getBytes(), + new NV ( family.getBytes(), "1".getBytes() , tableParts.get(family).toBytes() ) ) + ); + } + + HWriter.getInstance(true).insertScalar(schema.tableName, records); + } +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/SearchTester.java b/src/test/com/bizosys/hsearch/treetable/storage/SearchTester.java new file mode 100644 index 0000000..3d54915 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/SearchTester.java @@ -0,0 +1,346 @@ +package com.bizosys.hsearch.treetable.storage; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; +import junit.framework.TestFerrari; + +import com.bizosys.hsearch.treetable.Cell2Test; +import com.bizosys.hsearch.treetable.storage.sampleImpl.Client; +import com.oneline.ferrari.TestAll; + +public class SearchTester extends TestCase { + + public static String[] modes = new String[] { "all", "random", "method"}; + public static String mode = modes[2]; + + public static void main(String[] args) throws Exception { + SearchTester t = new SearchTester(); + + if ( modes[0].equals(mode) ) { + TestAll.run(new TestCase[]{t}); + } else if ( modes[1].equals(mode) ) { + TestFerrari.testRandom(t); + + } else if ( modes[2].equals(mode) ) { + t.setUp(); + t.threeQuery3PartTest(); + t.tearDown(); + } + } + + @Override + protected void setUp() throws Exception { + } + + @Override + protected void tearDown() throws Exception { + } + + public void leftBoundaryTest() throws Exception { + } + + public void rightBoundaryTest() throws Exception { + } + + public void oneQuery1PartTest() throws Exception { + Client ht = new Client(); + + //Before partition starts + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|-1"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals(0, ht.finalOutput.size()); + } + + //First partition start + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[0]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|0.0]")); + } + + //First partition middle + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0.5"); + ht.execute("ExamResult:1", multiQueryParts); + System.out.println ( ht.finalOutput.toString()); + assertEquals("[5]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|0.5]")); + } + + + //First partition end + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|1"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[10]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|1.0]")); + } + + //Middle partition start + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|4"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[40]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|4.0]")); + } + + //Middle partition middle + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|4.5"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[45]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|4.5]")); + } + + //Middle partition ends + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|5"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[50]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|5.0]")); + } + + //End partition start + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|9"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[90]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|9.0]")); + } + + //Middle partition middle + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|9.5"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[95]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|9.5]")); + } + + //Middle partition ends + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|10"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[100]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|10.0]")); + } + + //Beyond partition ends + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|11"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals(0, ht.finalOutput.size()); + } + + } + + public void oneQuery2PartTest() throws Exception { + } + + public void oneQuery3PartTest() throws Exception { + } + + public void twoQuery1PartTest() throws Exception { + Client ht = new Client(); + + //Before partition starts + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|-1"); + multiQueryParts.put("ExamResult:2", "*|*|*|*|0"); + ht.execute("ExamResult:1 OR ExamResult:2", multiQueryParts); + assertEquals(1, ht.finalOutput.size()); + assertEquals("[0]", ht.finalOutput.keySet().toString()); + + System.out.println(ht.finalOutput.values().toString()); + assertTrue( ht.finalOutput.values().toString().endsWith("|0.0]")); + } + + + //First partition start + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0"); + multiQueryParts.put("ExamResult:2", "*|*|*|*|0.6"); + ht.execute("ExamResult:1 OR ExamResult:2", multiQueryParts); + assertEquals(2, ht.finalOutput.size()); + assertEquals("[0, 6]", ht.finalOutput.keySet().toString()); + + System.out.println(ht.finalOutput.values().toString()); + assertTrue( ht.finalOutput.values().toString().matches(".+0\\.0,.+0\\.6\\]")); + } + + //First partition middle + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0.5"); + multiQueryParts.put("ExamResult:2", "*|*|*|*|0.6"); + ht.execute("ExamResult:1 OR ExamResult:2", multiQueryParts); + assertEquals(2, ht.finalOutput.size()); + assertEquals("[6, 5]", ht.finalOutput.keySet().toString()); + + System.out.println(ht.finalOutput.values().toString()); + assertTrue( ht.finalOutput.values().toString().matches(".+0\\.6,.+0\\.5\\]")); + } + + //First partition end + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0.5"); + multiQueryParts.put("ExamResult:2", "*|*|*|*|1.0"); + ht.execute("ExamResult:1 OR ExamResult:2", multiQueryParts); + assertEquals(2, ht.finalOutput.size()); + assertEquals("[10, 5]", ht.finalOutput.keySet().toString()); + + System.out.println(ht.finalOutput.values().toString()); + assertTrue( ht.finalOutput.values().toString().matches(".+0\\1.0,.+0\\0.5\\]")); + } + if ( 1 == 1 ) return; + + //Middle partition start + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|4"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[40]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|4.0]")); + } + + //Middle partition middle + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|4.5"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[45]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|4.5]")); + } + + //Middle partition ends + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|5"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[50]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|5.0]")); + } + + //End partition start + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|9"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[90]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|9.0]")); + } + + //Middle partition middle + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|9.5"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[95]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|9.5]")); + } + + //Middle partition ends + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|10"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals("[100]", ht.finalOutput.keySet().toString()); + assertTrue(ht.finalOutput.values().toString().endsWith("|10.0]")); + } + + //Beyond partition ends + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|11"); + ht.execute("ExamResult:1", multiQueryParts); + assertEquals(0, ht.finalOutput.size()); + } + } + + public void twoQuery2PartTest() throws Exception { + } + + public void twoQuery3PartTest() throws Exception { + } + + public void threeQuery1PartTest() throws Exception { + } + + public void threeQuery2PartTest() throws Exception { + } + + public void threeQuery3PartTest() throws Exception { + Client ht = new Client(); + + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0"); + multiQueryParts.put("ExamResult:2", "*|*|*|*|0.6"); + multiQueryParts.put("ExamResult:3", "*|*|*|*|10.0"); + ht.execute("ExamResult:1 OR ExamResult:2 OR ExamResult:3", multiQueryParts); + System.out.println(ht.finalOutput.toString()); + } + + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0"); + multiQueryParts.put("ExamResult:2", "*|*|*|*|0.6"); + multiQueryParts.put("ExamResult:3", "*|*|*|*|10.0"); + ht.execute("ExamResult:1 AND (ExamResult:2 OR ExamResult:3)", multiQueryParts); + System.out.println("Final :" + ht.finalOutput.toString()); + } + + { + ht.finalOutput.clear(); + Map multiQueryParts = new HashMap(); + multiQueryParts.put("ExamResult:1", "*|*|*|*|0"); + multiQueryParts.put("ExamResult:2", "*|*|*|*|0.6"); + multiQueryParts.put("ExamResult:3", "*|*|*|*|10.0"); + ht.execute("(ExamResult:1 AND ExamResult:2) OR ExamResult:3", multiQueryParts); + System.out.println("Final :" + ht.finalOutput.toString()); + } + + } + +} \ No newline at end of file diff --git a/src/test/com/bizosys/hsearch/treetable/storage/examresult.json b/src/test/com/bizosys/hsearch/treetable/storage/examresult.json new file mode 100644 index 0000000..226f1aa --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/examresult.json @@ -0,0 +1,47 @@ +{ + "module" : "com.bizosys.hsearch.treetable.storage.sampleImpl", + "table": "htable-test", + "columns": [ + { + "name": "ExamResult", + + "mergeId": { + "name": "mergeId", + "datatype": "Integer" + }, + + "indexes": [ + { + "name": "age", + "datatype": "Integer" + }, + { + "name": "role", + "datatype": "String" + }, + { + "name": "location", + "datatype": "String" + } + ], + + "key": { + "name": "empid", + "datatype": "Integer" + }, + + "value": + { + "name": "mark", + "datatype": "Float" + }, + + "partitions": { + "names": "a,b,c,d,e,f,g,h,i,j", + "ranges": "[*:1],[1:2],[2:3],[3:4],[4:5],[5:6],[6:7],[7:8],[8:9],[9:*]", + "column" : 4 , + "type" : "numeric" + } + } + ] +} \ No newline at end of file diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Client.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Client.java new file mode 100644 index 0000000..1ecb0ad --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Client.java @@ -0,0 +1,73 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl; + +import java.awt.List; +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import com.bizosys.hsearch.byteutils.SortedBytesArray; +import com.bizosys.hsearch.byteutils.SortedBytesBase.Reference; +import com.bizosys.hsearch.byteutils.SortedBytesString; +import com.bizosys.hsearch.treetable.BytesSection; +import com.bizosys.hsearch.treetable.Cell2; +import com.bizosys.hsearch.treetable.CellKeyValue; +import com.bizosys.hsearch.treetable.client.HSearchProcessingInstruction; +import com.bizosys.hsearch.treetable.storage.HSearchGenericFilter; +import com.bizosys.hsearch.treetable.storage.HSearchTableReader; +import com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify.HBaseTableSchema; + +public class Client extends HSearchTableReader { + + HSearchGenericFilter filter = null; + + public Map finalOutput = new HashMap(); + + public Client() throws IOException { + HBaseTableSchema.getInstance(); + } + + @Override + public HSearchGenericFilter getFilter(String multiQuery, + Map multiQueryParts, HSearchProcessingInstruction outputType) { + filter = new Filter(outputType, multiQuery, multiQueryParts); + return filter; + } + + @Override + public void rows(Map results, HSearchProcessingInstruction instruction) { + + try { + + for (Map.Entry entry : results.entrySet()) { + + byte[] data = entry.getValue(); + SortedBytesArray arr = SortedBytesArray.getInstanceArr(); + arr.parse(data); + + int size = arr.getSize(); + SortedBytesArray.Reference ref = new SortedBytesArray.Reference(); + for ( int i=0; i cell2 = new Cell2( + SortedBytesString.getInstance(), SortedBytesString.getInstance(), + new BytesSection(data, ref.offset, ref.length)); + + cell2.populate(finalOutput); + } + } + + } catch (IOException ex) { + ex.printStackTrace(System.out); + } + + } + + public void execute(String query, Map qPart) throws IOException, ParseException { + HSearchProcessingInstruction instruction = + new HSearchProcessingInstruction(HSearchProcessingInstruction.PLUGIN_CALLBACK_COLS, HSearchProcessingInstruction.OUTPUT_COLS); + read(query, qPart, instruction , true, true); + } +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Filter.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Filter.java new file mode 100644 index 0000000..e6c90c8 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Filter.java @@ -0,0 +1,47 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl; + +import java.io.IOException; +import java.util.Map; + +import com.bizosys.hsearch.functions.HSearchReducer; +import com.bizosys.hsearch.hbase.HbaseLog; +import com.bizosys.hsearch.treetable.client.HSearchProcessingInstruction; +import com.bizosys.hsearch.treetable.client.HSearchTableMultiQueryExecutor; +import com.bizosys.hsearch.treetable.client.IHSearchPlugin; +import com.bizosys.hsearch.treetable.storage.HSearchGenericFilter; +import com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify.HSearchTableMultiQueryProcessorImpl; + +public class Filter extends HSearchGenericFilter { + + public static boolean DEBUG_ENABLED = HbaseLog.l.isDebugEnabled(); + + public Filter(){ + } + public Filter(HSearchProcessingInstruction outputType, String query,Map details) { + super(outputType, query, details); + } + + @Override + public HSearchTableMultiQueryExecutor createExecutor() { + return new HSearchTableMultiQueryExecutor(new HSearchTableMultiQueryProcessorImpl()); + } + + @Override + public IHSearchPlugin createPlugIn(String type) throws IOException { + if (DEBUG_ENABLED) { + HbaseLog.l.debug(Thread.currentThread().getId()+ " > HBaseHSearchFilter : type > " + type); + } + + if ( type.equals("ExamResult") ) { + return new MapperExamResult(); + } + + + throw new IOException("Unknown Column Type :" + type); + } + + @Override + public HSearchReducer getReducer() { + return new Reducer(); + } +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/MapperExamResult.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/MapperExamResult.java new file mode 100644 index 0000000..ee084b4 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/MapperExamResult.java @@ -0,0 +1,180 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.bizosys.hsearch.byteutils.SortedBytesArray; +import com.bizosys.hsearch.byteutils.SortedBytesString; +import com.bizosys.hsearch.byteutils.Storable; +import com.bizosys.hsearch.federate.FederatedFacade; +import com.bizosys.hsearch.treetable.Cell2; +import com.bizosys.hsearch.treetable.client.HSearchProcessingInstruction; +import com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify.PluginExamResultBase; + +public class MapperExamResult extends PluginExamResultBase { + + public static String EMPTY = ""; + static boolean DEBUG_ENABLED = false; + static byte[] bytesFor1 = Storable.putInt(1); + + HSearchProcessingInstruction instruction = null; + + Map rows = new HashMap(); + + @Override + public void setOutputType(HSearchProcessingInstruction outputTypeCode) { + this.instruction = outputTypeCode; + } + + /** + * Merge is called when all threads finish their processing. + * It can so happen that all threads may call at same time. + * Maintain thread concurrency in the code. + * Don't remove this.parts.remove(); as after merging, it clears the ThreadLocal object. + */ + protected void merge(Map rows) { + synchronized (this) { + this.rows.putAll(rows); + } + System.out.println("Number of Rows :" + this.rows.size()); + this.parts.remove(); + } + + /** + * When all parts are completed, finally it is called. + * By this time, the result of all parts is available for final processing. + * + */ + @Override + public void onReadComplete() { + } + + + /** + * For multi queries, we need to provide matching documents for + * intersection. For sinle query this is having no usage and can be passed null to save computing. + */ + @Override + public Collection getUniqueMatchingDocumentIds() throws IOException { + return this.rows.keySet(); + } + + /** + * Collects the results for rows level aggregation. + */ + @Override + public void getResultSingleQuery(Collection container) throws IOException { + Cell2 cell2 = new Cell2(SortedBytesString.getInstance(), + SortedBytesString.getInstance()); + + byte[] keyVal = cell2.toBytesOnSortedData(rows); + container.add(keyVal); + } + + /** + * Collects the results for rows level aggregation. + */ + @Override + public void getResultMultiQuery(List.IRowId> matchedIds, + Collection container) throws IOException { + + Cell2 cell2 = new Cell2(SortedBytesString.getInstance(), + SortedBytesString.getInstance()); + + for (FederatedFacade.IRowId row : matchedIds) { + String docId = row.getDocId(); + if ( ! rows.containsKey(docId) ) continue; + cell2.add(docId, rows.get(docId)); + } + container.add(cell2.toBytesOnSortedData()); + } + + /** + * This method is finally called which cleans up all the resources. + * If not cleaned up the results will be contaminated + */ + @Override + public void clear() { + this.rows.clear(); + } + + /** + * Each thread will have 1 instance of this class. + * For all found rows, the onRowCols/onRowKeys/... are called as we have set in the instructor. + * @see Client.execute + * When all are processed, this reports back to the main class for agrregating the result via merge. + * @see Mapper.whole.merge + * @author abinash + * + */ + public static class RowReader implements TablePartsCallback { + + Map rows = new HashMap(); + public MapperExamResult whole = null; + + public RowReader(MapperExamResult whole) { + this.whole = whole; + } + + public final boolean onRowKey(int id) { + return true; + } + + public final boolean onRowCols(int cell1, String cell2, String cell3, int studentId, float cell5) { + String rowAsStr = "" + cell1 + "|" + cell2 + "|" + cell3 + "|" + studentId + "|" + cell5; + rows.put(new Integer(studentId).toString(), rowAsStr); + System.out.println(rowAsStr); + return true; + } + + @Override + public final boolean onRowKeyValue(int key, float value) { + return true; + } + + @Override + public final boolean onRowValue(float value) { + return true; + } + + @Override + public void onReadComplete() { + this.whole.merge(rows); + rows.clear(); + /** + * Clean up resources for reuse. + */ + } + } + + /******************************************************************************************* + * The below sections are generic in nature and no need to be changed. + */ + /** + * Do not modify this section as we need to create indivisual instances per thread. + */ + public ThreadLocal parts = + new ThreadLocal(); + @Override + public PluginExamResultBase.TablePartsCallback getPart() { + PluginExamResultBase.TablePartsCallback part = parts.get(); + if (null == part) { + parts.set(new RowReader(this)); + return parts.get(); + } + return part; + } + + /** + * sample ser/deser. Use Storable class. + public static byte[] ser(int findings, int groups, int studies) { + byte[] output = new byte[12]; + System.arraycopy(Storable.putInt(cell1), 0, output, 0, 4); + System.arraycopy(Storable.putFloat(cell2), 0, output, 4, 4); + return output; + } + */ +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Reducer.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Reducer.java new file mode 100644 index 0000000..c374ce3 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/Reducer.java @@ -0,0 +1,35 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl; + +import java.util.Collection; + +import com.bizosys.hsearch.functions.HSearchReducer; + +public class Reducer implements HSearchReducer { + + @Override + public void appendCols(Collection mergedB, Collection appendB) { + + System.out.println("appendCols"); + if (null == appendB) return; + if (appendB.size() == 0) return; + + for (byte[] bs : appendB) { + if ( null == bs) continue; + mergedB.add(bs); + } + } + + @Override + public void appendRows(Collection mergedB, Collection appendB) { + System.out.println("appendRows"); + if (null == appendB) return; + if (appendB.size() == 0) return; + + mergedB.addAll(appendB); + } + + @Override + public void appendRows(Collection mergedRows, byte[] appendRowId, Collection appendRows) { + appendRows(mergedRows, appendRows); + } +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HBaseTableSchema.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HBaseTableSchema.java new file mode 100644 index 0000000..140f4d6 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HBaseTableSchema.java @@ -0,0 +1,46 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify; + +import java.io.IOException; +import java.util.Map; + +import com.bizosys.hsearch.treetable.client.partition.IPartition; +import com.bizosys.hsearch.treetable.client.partition.PartitionNumeric; +import com.bizosys.hsearch.treetable.client.partition.PartitionByFirstLetter; + +import com.bizosys.hsearch.treetable.storage.HBaseTableSchemaCreator; +import com.bizosys.hsearch.treetable.storage.HBaseTableSchemaDefn; + +public class HBaseTableSchema { + + private static HBaseTableSchema singleton = null; + + public static HBaseTableSchema getInstance() throws IOException { + if ( null == singleton ) singleton = new HBaseTableSchema(); + return singleton; + } + + private HBaseTableSchema() throws IOException { + + HBaseTableSchemaDefn.getInstance().tableName = "htable-test"; + Map columns = HBaseTableSchemaDefn.getInstance().columnPartions; + columns.put("ExamResult",new PartitionNumeric()); + columns.get("ExamResult").setPartitionsAndRange( + "ExamResult", + "a,b,c,d,e,f,g,h,i,j", + "[*:1],[1:2],[2:3],[3:4],[4:5],[5:6],[6:7],[7:8],[8:9],[9:*]", + 4); + + } + + public HBaseTableSchemaDefn getSchema() { + return HBaseTableSchemaDefn.getInstance(); + } + + public void createSchema() { + new HBaseTableSchemaCreator().init(); + } + + public static void main(String[] args) throws Exception { + HBaseTableSchema.getInstance().createSchema(); + } +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableCombinerImpl.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableCombinerImpl.java new file mode 100644 index 0000000..039f9b1 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableCombinerImpl.java @@ -0,0 +1,19 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify; + +import java.io.IOException; + +import com.bizosys.hsearch.treetable.client.HSearchTableCombiner; +import com.bizosys.hsearch.treetable.client.IHSearchTable; + +public class HSearchTableCombinerImpl extends HSearchTableCombiner { + + @Override + public IHSearchTable buildTable(String tableType) throws IOException { + + if ( tableType.equals("ExamResult")) return new HSearchTableExamResult(); + + + throw new IOException("Class not found. Missing class HSearchTable" + tableType ); + + } +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableExamResult.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableExamResult.java new file mode 100644 index 0000000..a1e2801 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableExamResult.java @@ -0,0 +1,345 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.bizosys.hsearch.byteutils.SortedBytesArray; +import com.bizosys.hsearch.byteutils.SortedBytesDouble; +import com.bizosys.hsearch.byteutils.SortedBytesLong; +import com.bizosys.hsearch.byteutils.SortedBytesFloat; +import com.bizosys.hsearch.byteutils.SortedBytesInteger; +import com.bizosys.hsearch.byteutils.SortedBytesUnsignedShort; +import com.bizosys.hsearch.byteutils.SortedBytesChar; +import com.bizosys.hsearch.byteutils.SortedBytesBoolean; +import com.bizosys.hsearch.byteutils.SortedBytesString; + +import com.bizosys.hsearch.treetable.storage.sampleImpl.*; + +import com.bizosys.hsearch.treetable.Cell2; +import com.bizosys.hsearch.treetable.Cell3; +import com.bizosys.hsearch.treetable.Cell4; +import com.bizosys.hsearch.treetable.Cell5; + +import com.bizosys.hsearch.treetable.BytesSection; +import com.bizosys.hsearch.treetable.Cell2Visitor; +import com.bizosys.hsearch.treetable.CellBase; + +import com.bizosys.hsearch.treetable.client.HSearchQuery; +import com.bizosys.hsearch.treetable.client.IHSearchPlugin; +import com.bizosys.hsearch.treetable.client.IHSearchTable; + +import com.bizosys.hsearch.treetable.CellComparator; +import com.bizosys.hsearch.treetable.CellComparator.BooleanComparator; +import com.bizosys.hsearch.treetable.CellComparator.ByteComparator; +import com.bizosys.hsearch.treetable.CellComparator.BytesComparator; +import com.bizosys.hsearch.treetable.CellComparator.ShortComparator; +import com.bizosys.hsearch.treetable.CellComparator.IntegerComparator; +import com.bizosys.hsearch.treetable.CellComparator.FloatComparator; +import com.bizosys.hsearch.treetable.CellComparator.LongComparator; +import com.bizosys.hsearch.treetable.CellComparator.DoubleComparator; +import com.bizosys.hsearch.treetable.CellComparator.StringComparator; +import com.bizosys.hsearch.treetable.ValueComparator; +import com.bizosys.hsearch.util.EmptyMap; + +public class HSearchTableExamResult implements IHSearchTable { + + public static boolean DEBUG_ENABLED = false; + + public static final int MODE_COLS = 0; + public static final int MODE_KEY = 1; + public static final int MODE_VAL = 2; + public static final int MODE_KEYVAL = 3; + + + public static final class Cell4Map + extends EmptyMap> { + + public HSearchQuery query; + public Cell2FilterVisitor cell2Visitor; + public String matchingCell1; + public String cellMin1; + public String cellMax1; + public Map> cell3L = null; + + public Cell4Map(HSearchQuery query, Cell2FilterVisitor cell2Visitor,Float matchingCell4, Float cellMin4, Float cellMax4,String matchingCell2, String cellMin2, String cellMax2,String matchingCell1, String cellMin1, String cellMax1) { + this.query = query; + this.cell2Visitor = cell2Visitor; + this.matchingCell1 = matchingCell1; + this.cellMin1 = cellMin1; + this.cellMax1 = cellMax1; + this.cell3L = new Cell3Map(query, cell2Visitor,matchingCell4, cellMin4, cellMax4,matchingCell2, cellMin2, cellMax2); + } + @Override + public Cell4 put(Integer key, Cell4 value) { + try { + cell2Visitor.cell4Key = key; + if (query.filterCells[1]) { + value.getMap(matchingCell1, cellMin1, cellMax1, cell3L); + } else { + value.sortedList = cell3L; + value.parseElements(); + } + return value; + } catch (IOException e) { + throw new IndexOutOfBoundsException(e.getMessage()); + } + } +} + + +public static final class Cell3Map + extends EmptyMap> { + + public HSearchQuery query; + public Cell2FilterVisitor cell2Visitor; + public String matchingCell2; + public String cellMin2; + public String cellMax2; + public Map> cell2L = null; + + public Cell3Map(HSearchQuery query, Cell2FilterVisitor cell2Visitor,Float matchingCell4, Float cellMin4, Float cellMax4,String matchingCell2, String cellMin2, String cellMax2) { + this.query = query; + this.cell2Visitor = cell2Visitor; + this.matchingCell2 = matchingCell2; + this.cellMin2 = cellMin2; + this.cellMax2 = cellMax2; + this.cell2L = new Cell2Map(query, cell2Visitor,matchingCell4, cellMin4, cellMax4); + } + @Override + public Cell3 put(String key, Cell3 value) { + try { + cell2Visitor.cell3Key = key; + if (query.filterCells[2]) { + value.getMap(matchingCell2, cellMin2, cellMax2, cell2L); + } else { + value.sortedList = cell2L; + value.parseElements(); + } + return value; + } catch (IOException e) { + throw new IndexOutOfBoundsException(e.getMessage()); + } + } +} + + + + + public static final class Cell2Map extends EmptyMap> { + + public HSearchQuery query; + public Float matchingCell4; + public Float cellMin4; + public Float cellMax4; + public Cell2FilterVisitor cell2Visitor; + + public Cell2Map(HSearchQuery query, Cell2FilterVisitor cell2Visitor, + Float matchingCell4, Float cellMin4, Float cellMax4) { + this.query = query; + this.cell2Visitor = cell2Visitor; + + this.matchingCell4 = matchingCell4; + this.cellMin4 = cellMin4; + this.cellMax4 = cellMax4; + } + + @Override + public Cell2 put(String key, Cell2 value) { + + try { + cell2Visitor.cell2Key = key; + Cell2 cell2Val = value; + + if (query.filterCells[4]) { + cell2Val.process(matchingCell4, cellMin4, cellMax4,cell2Visitor); + } else { + cell2Val.process(cell2Visitor); + } + return value; + } catch (IOException e) { + throw new IndexOutOfBoundsException(e.getMessage()); + } + } + } + + /////////////////////////////////////////////////////////////////// + + public static final class Cell2FilterVisitor implements Cell2Visitor { + public HSearchQuery query; + public IHSearchPlugin plugin; + + public PluginExamResultBase.TablePartsCallback tablePartsCallback = null; + + public Integer matchingCell3; + public Integer cellMin3; + public Integer cellMax3; + + public int cell4Key; + public String cell3Key; + public String cell2Key; + + public int mode = MODE_COLS; + public Cell2FilterVisitor(HSearchQuery query,IHSearchPlugin plugin, PluginExamResultBase.TablePartsCallback tablePartsCallback, int mode) { + + this.query = query; + this.plugin = plugin; + this.tablePartsCallback = tablePartsCallback; + this.mode = mode; + + } + + public void set(Integer matchingCell3, Integer cellMin3, Integer cellMax3) { + this.matchingCell3 = matchingCell3; + this.cellMin3 = cellMin3; + this.cellMax3 = cellMax3; + } + + + + @Override + public final void visit(Integer cell1Key, Float cell1Val) { + if (query.filterCells[3]) { + if (null != matchingCell3) { + if (matchingCell3.intValue() != cell1Key.intValue()) return; + } else { + if (cell1Key.intValue() < cellMin3.intValue() || cell1Key.intValue() > cellMax3.intValue()) return; + } + } + + if (null != plugin) { + switch (this.mode) { + case MODE_COLS : + tablePartsCallback.onRowCols(cell4Key, cell3Key, cell2Key, cell1Key, cell1Val); + break; + + case MODE_KEY : + tablePartsCallback.onRowKey(cell1Key); + break; + case MODE_KEYVAL : + tablePartsCallback.onRowKeyValue(cell1Key, cell1Val); + break; + case MODE_VAL: + tablePartsCallback.onRowValue(cell1Val); + break; + } + } + } + } + + /////////////////////////////////////////////////////////////////// + + Cell5 table = createBlankTable(); + + public HSearchTableExamResult() { + } + + public Cell5 createBlankTable() { + return new Cell5 + ( + SortedBytesInteger.getInstance(), + SortedBytesString.getInstance(), + SortedBytesString.getInstance(), + SortedBytesInteger.getInstance(), + SortedBytesFloat.getInstance() + ); + } + + public byte[] toBytes() throws IOException { + if ( null == table) return null; + return table.toBytes(new FloatComparator()); + } + + public void put (Integer age, String role, String location, Integer empid, Float mark) { + table.put( age, role, location, empid, mark ); + } + + @Override + public void get(byte[] input, HSearchQuery query, IHSearchPlugin pluginI) throws IOException, NumberFormatException { + iterate(input, query, pluginI, MODE_COLS); + } + + @Override + public void keySet(byte[] input, HSearchQuery query, IHSearchPlugin pluginI) throws IOException { + iterate(input, query, pluginI, MODE_KEY); + } + + public void values(byte[] input, HSearchQuery query, IHSearchPlugin pluginI) throws IOException { + iterate(input, query, pluginI, MODE_VAL); + } + + public void keyValues(byte[] input, HSearchQuery query, IHSearchPlugin pluginI) throws IOException { + iterate(input, query, pluginI, MODE_KEYVAL); + } + + private void iterate(byte[] input, HSearchQuery query, IHSearchPlugin pluginI, int mode) throws IOException, NumberFormatException { + + PluginExamResultBase plugin = castPlugin(pluginI); + PluginExamResultBase.TablePartsCallback callback = plugin.getPart(); + + Cell2FilterVisitor cell2Visitor = new Cell2FilterVisitor(query, pluginI, callback, mode); + + query.parseValuesConcurrent(new String[]{"Integer", "String", "String", "Integer", "Float"}); + + Integer matchingCell0 = ( query.filterCells[0] ) ? (Integer) query.exactValCellsO[0]: null; + String matchingCell1 = ( query.filterCells[1] ) ? (String) query.exactValCellsO[1]: null; + String matchingCell2 = ( query.filterCells[2] ) ? (String) query.exactValCellsO[2]: null; + cell2Visitor.matchingCell3 = ( query.filterCells[3] ) ? (Integer) query.exactValCellsO[3]: null; + Float matchingCell4 = ( query.filterCells[4] ) ? (Float) query.exactValCellsO[4]: null; + + + Integer cellMin0 = ( query.minValCells[0] == HSearchQuery.DOUBLE_MIN_VALUE) ? null : new Double(query.minValCells[0]).intValue(); + String cellMin1 = null; + String cellMin2 = null; + cell2Visitor.cellMin3 = ( query.minValCells[3] == HSearchQuery.DOUBLE_MIN_VALUE) ? null : new Double(query.minValCells[3]).intValue(); + Float cellMin4 = ( query.minValCells[4] == HSearchQuery.DOUBLE_MIN_VALUE) ? null : new Double(query.minValCells[4]).floatValue(); + + + Integer cellMax0 = (query.maxValCells[0] == HSearchQuery.DOUBLE_MAX_VALUE) ? null : new Double(query.maxValCells[0]).intValue(); + String cellMax1 = null; + String cellMax2 = null; + cell2Visitor.cellMax3 = (query.maxValCells[3] == HSearchQuery.DOUBLE_MAX_VALUE) ? null : new Double(query.maxValCells[3]).intValue(); + Float cellMax4 = (query.maxValCells[4] == HSearchQuery.DOUBLE_MAX_VALUE) ? null : new Double(query.maxValCells[4]).floatValue(); + + + Cell4Map cell4L = new Cell4Map(query, cell2Visitor,matchingCell4, cellMin4, cellMax4,matchingCell2, cellMin2, cellMax2,matchingCell1, cellMin1, cellMax1); + + this.table.data = new BytesSection(input); + if (query.filterCells[0]) { + this.table.getMap(matchingCell0, cellMin0, cellMax0, cell4L); + } else { + this.table.sortedList = cell4L; + this.table.parseElements(); + } + + if (null != callback) callback.onReadComplete(); + if (null != plugin) plugin.onReadComplete(); + } + + public PluginExamResultBase castPlugin(IHSearchPlugin pluginI) + throws IOException { + PluginExamResultBase plugin = null; + if (null != pluginI) { + if (pluginI instanceof PluginExamResultBase) { + plugin = (PluginExamResultBase) pluginI; + } + if (null == plugin) { + throw new IOException("Invalid plugin Type :" + pluginI); + } + } + return plugin; + } + + /** + * Free the cube data + */ + public void clear() throws IOException { + table.getMap().clear(); + } + +} + \ No newline at end of file diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableMultiQueryProcessorImpl.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableMultiQueryProcessorImpl.java new file mode 100644 index 0000000..8fd16c9 --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/HSearchTableMultiQueryProcessorImpl.java @@ -0,0 +1,17 @@ +package com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify; + +import com.bizosys.hsearch.treetable.client.HSearchTableMultiQueryProcessor; +import com.bizosys.hsearch.treetable.client.IHSearchTableCombiner; + +public class HSearchTableMultiQueryProcessorImpl extends HSearchTableMultiQueryProcessor { + + public HSearchTableMultiQueryProcessorImpl() { + super(); + } + + @Override + public IHSearchTableCombiner getCombiner() { + return new HSearchTableCombinerImpl(); + } + +} diff --git a/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/PluginExamResultBase.java b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/PluginExamResultBase.java new file mode 100644 index 0000000..783649d --- /dev/null +++ b/src/test/com/bizosys/hsearch/treetable/storage/sampleImpl/donotmodify/PluginExamResultBase.java @@ -0,0 +1,21 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.bizosys.hsearch.treetable.storage.sampleImpl.donotmodify; + +import com.bizosys.hsearch.treetable.client.IHSearchPlugin; + +public abstract class PluginExamResultBase implements IHSearchPlugin { + + public abstract TablePartsCallback getPart(); + + public interface TablePartsCallback { + + boolean onRowKey(int id); + public boolean onRowCols(int cell1, String cell2, String cell3, int cell4, float cell5); + public boolean onRowKeyValue(int key, float value); + public boolean onRowValue(float value); + public void onReadComplete(); + } +}