23
23
import com .alipay .oceanbase .hbase .filter .HBaseFilterUtils ;
24
24
import com .alipay .oceanbase .hbase .result .ClientStreamScanner ;
25
25
import com .alipay .oceanbase .hbase .util .*;
26
+ import com .alipay .oceanbase .rpc .ObGlobal ;
26
27
import com .alipay .oceanbase .rpc .ObTableClient ;
27
28
import com .alipay .oceanbase .rpc .exception .ObTableException ;
29
+ import com .alipay .oceanbase .rpc .exception .ObTableUnexpectedException ;
28
30
import com .alipay .oceanbase .rpc .mutation .BatchOperation ;
29
31
import com .alipay .oceanbase .rpc .mutation .result .BatchOperationResult ;
32
+ import com .alipay .oceanbase .rpc .mutation .result .MutationResult ;
33
+ import com .alipay .oceanbase .rpc .protocol .payload .ObPayload ;
30
34
import com .alipay .oceanbase .rpc .protocol .payload .impl .ObObj ;
31
35
import com .alipay .oceanbase .rpc .protocol .payload .impl .ObRowKey ;
32
36
import com .alipay .oceanbase .rpc .protocol .payload .impl .execute .*;
39
43
import com .alipay .oceanbase .rpc .stream .ObTableClientQueryStreamResult ;
40
44
import com .alipay .oceanbase .rpc .table .ObHBaseParams ;
41
45
import com .alipay .oceanbase .rpc .table .ObKVParams ;
46
+ import com .alipay .oceanbase .rpc .table .ObTableClientQueryImpl ;
42
47
import com .alipay .sofa .common .thread .SofaThreadPoolExecutor ;
43
48
44
49
import com .google .protobuf .Descriptors ;
68
73
import static com .alipay .oceanbase .hbase .util .Preconditions .checkNotNull ;
69
74
import static com .alipay .oceanbase .hbase .util .TableHBaseLoggerFactory .LCD ;
70
75
import static com .alipay .oceanbase .hbase .util .TableHBaseLoggerFactory .TABLE_HBASE_LOGGER_SPACE ;
76
+ import static com .alipay .oceanbase .rpc .mutation .MutationFactory .colVal ;
77
+ import static com .alipay .oceanbase .rpc .mutation .MutationFactory .row ;
71
78
import static com .alipay .oceanbase .rpc .protocol .payload .impl .execute .ObTableOperation .getInstance ;
72
79
import static com .alipay .oceanbase .rpc .protocol .payload .impl .execute .ObTableOperationType .*;
73
80
import static com .alipay .sofa .common .thread .SofaThreadPoolConstants .SOFA_THREAD_POOL_LOGGING_CAPABILITY ;
@@ -523,8 +530,18 @@ public boolean exists(Get get) throws IOException {
523
530
@ Override
524
531
public boolean [] existsAll (List <Get > gets ) throws IOException {
525
532
boolean [] ret = new boolean [gets .size ()];
526
- for (int i = 0 ; i < gets .size (); ++i ) {
527
- ret [i ] = exists (gets .get (i ));
533
+ List <Get > newGets = new ArrayList <>();
534
+ // if just checkExistOnly, batch get will not return any result or row count
535
+ // therefore we have to set checkExistOnly as false and so the result can be returned
536
+ // TODO: adjust ExistOnly in server when using batch get
537
+ for (Get get : gets ) {
538
+ Get newGet = new Get (get );
539
+ newGet .setCheckExistenceOnly (false );
540
+ newGets .add (newGet );
541
+ }
542
+ Result [] results = get (newGets );
543
+ for (int i = 0 ; i < results .length ; ++i ) {
544
+ ret [i ] = !results [i ].isEmpty ();
528
545
}
529
546
return ret ;
530
547
}
@@ -681,7 +698,7 @@ private void compatOldServerBatch(final List<? extends Row> actions, final Objec
681
698
}
682
699
683
700
@ Override
684
- public void batch (final List <? extends Row > actions , final Object [] results ) throws IOException {
701
+ public void batch (final List <? extends Row > actions , final Object [] results ) throws IOException {
685
702
if (actions == null ) {
686
703
return ;
687
704
}
@@ -693,7 +710,7 @@ public void batch(final List<? extends Row> actions, final Object[] results) thr
693
710
BatchError batchError = new BatchError ();
694
711
obTableClient .setRuntimeBatchExecutor (executePool );
695
712
List <Integer > resultMapSingleOp = new LinkedList <>();
696
- if (!CompatibilityUtil . isBatchSupport ()) {
713
+ if (!ObGlobal . isHBaseBatchSupport ()) {
697
714
try {
698
715
compatOldServerBatch (actions , results , batchError );
699
716
} catch (Exception e ) {
@@ -716,6 +733,23 @@ public void batch(final List<? extends Row> actions, final Object[] results) thr
716
733
results [i ] = tmpResults .getResults ().get (index );
717
734
}
718
735
batchError .add ((ObTableException ) tmpResults .getResults ().get (index ), actions .get (i ), null );
736
+ } else if (actions .get (i ) instanceof Get ) {
737
+ if (results != null ) {
738
+ // get results have been wrapped in MutationResult, need to fetch it
739
+ if (tmpResults .getResults ().get (index ) instanceof MutationResult ) {
740
+ MutationResult mutationResult = (MutationResult ) tmpResults .getResults ().get (index );
741
+ ObPayload innerResult = mutationResult .getResult ();
742
+ if (innerResult instanceof ObTableSingleOpResult ) {
743
+ ObTableSingleOpResult singleOpResult = (ObTableSingleOpResult ) innerResult ;
744
+ List <Cell > cells = generateGetResult (singleOpResult );
745
+ results [i ] = Result .create (cells );
746
+ } else {
747
+ throw new ObTableUnexpectedException ("Unexpected type of result in MutationResult" );
748
+ }
749
+ } else {
750
+ throw new ObTableUnexpectedException ("Unexpected type of result in batch" );
751
+ }
752
+ }
719
753
} else {
720
754
if (results != null ) {
721
755
results [i ] = new Result ();
@@ -729,17 +763,57 @@ public void batch(final List<? extends Row> actions, final Object[] results) thr
729
763
}
730
764
}
731
765
766
+ private List <Cell > generateGetResult (ObTableSingleOpResult getResult ) throws IOException {
767
+ List <Cell > cells = new ArrayList <>();
768
+ ObTableSingleOpEntity singleOpEntity = getResult .getEntity ();
769
+ // all values queried by this get are contained in properties
770
+ // qualifier in batch get result is always appended after family
771
+ List <ObObj > propertiesValues = singleOpEntity .getPropertiesValues ();
772
+ int valueIdx = 0 ;
773
+ while (valueIdx < propertiesValues .size ()) {
774
+ // values in propertiesValues like: [ K, Q, T, V, K, Q, T, V ... ]
775
+ // we need to retrieve K Q T V and construct them to cells: [ cell_0, cell_1, ... ]
776
+ byte [][] familyAndQualifier = new byte [2 ][];
777
+ try {
778
+ // split family and qualifier
779
+ familyAndQualifier = OHBaseFuncUtils
780
+ .extractFamilyFromQualifier ((byte []) propertiesValues .get (valueIdx + 1 ).getValue ());
781
+ } catch (Exception e ) {
782
+ throw new IOException (e );
783
+ }
784
+ KeyValue kv = new KeyValue ((byte []) propertiesValues .get (valueIdx ).getValue (),//K
785
+ familyAndQualifier [0 ], // family
786
+ familyAndQualifier [1 ], // qualifiermat
787
+ (Long ) propertiesValues .get (valueIdx + 2 ).getValue (), // T
788
+ (byte []) propertiesValues .get (valueIdx + 3 ).getValue ()// V
789
+ );
790
+ cells .add (kv );
791
+ valueIdx += 4 ;
792
+ }
793
+ return cells ;
794
+ }
795
+
732
796
private String getTargetTableName (List <? extends Row > actions ) {
733
797
byte [] family = null ;
734
798
for (Row action : actions ) {
735
799
if (action instanceof RowMutations || action instanceof RegionCoprocessorServiceExec ) {
736
800
throw new FeatureNotSupportedException ("not supported yet'" );
737
801
} else {
738
- Mutation mutation = (Mutation ) action ;
739
- if (mutation .getFamilyCellMap ().size () != 1 ) {
802
+ Set <byte []> familySet = null ;
803
+ if (action instanceof Get ){
804
+ Get get = (Get ) action ;
805
+ familySet = get .familySet ();
806
+ } else {
807
+ Mutation mutation = (Mutation ) action ;
808
+ familySet = mutation .getFamilyCellMap ().keySet ();
809
+ }
810
+ if (familySet == null ) {
811
+ throw new ObTableUnexpectedException ("Fail to get family set in action" );
812
+ }
813
+ if (familySet .size () != 1 ) {
740
814
return getTargetTableName (tableNameString );
741
815
} else {
742
- byte [] nextFamily = mutation . getFamilyCellMap (). keySet () .iterator ().next ();
816
+ byte [] nextFamily = familySet .iterator ().next ();
743
817
if (family != null && !Arrays .equals (family , nextFamily )) {
744
818
return getTargetTableName (tableNameString );
745
819
} else if (family == null ) {
@@ -825,8 +899,8 @@ private String getTargetTableName(String tableNameString) {
825
899
return tableNameString ;
826
900
}
827
901
828
- // To enable the server to identify the column family to which a qualifier belongs,
829
- // the client writes the column family name into the qualifier.
902
+ // To enable the server to identify the column family to which a qualifier belongs,
903
+ // the client writes the column family name into the qualifier.
830
904
// The server then parses this information to determine the table that needs to be operated on.
831
905
private void processColumnFilters (NavigableSet <byte []> columnFilters ,
832
906
Map <byte [], NavigableSet <byte []>> familyMap ) {
@@ -862,8 +936,8 @@ public Result call() throws IOException {
862
936
if (get .getFamilyMap ().keySet () == null
863
937
|| get .getFamilyMap ().keySet ().isEmpty ()
864
938
|| get .getFamilyMap ().size () > 1 ) {
865
- // In a Get operation where the family map is greater than 1 or equal to 0,
866
- // we handle this by appending the column family to the qualifier on the client side.
939
+ // In a Get operation where the family map is greater than 1 or equal to 0,
940
+ // we handle this by appending the column family to the qualifier on the client side.
867
941
// The server can then use this information to filter the appropriate column families and qualifiers.
868
942
if (!get .getColumnFamilyTimeRange ().isEmpty ()) {
869
943
throw new FeatureNotSupportedException ("setColumnFamilyTimeRange is only supported in single column family for now" );
@@ -920,8 +994,12 @@ public Result call() throws IOException {
920
994
@ Override
921
995
public Result [] get (List <Get > gets ) throws IOException {
922
996
Result [] results = new Result [gets .size ()];
923
- for (int i = 0 ; i < gets .size (); i ++) {
924
- results [i ] = get (gets .get (i ));
997
+ if (ObGlobal .isHBaseBatchGetSupport ()) { // get only supported in BatchSupport version
998
+ batch (gets , results );
999
+ } else {
1000
+ for (int i = 0 ; i < gets .size (); i ++) {
1001
+ results [i ] = get (gets .get (i ));
1002
+ }
925
1003
}
926
1004
return results ;
927
1005
}
@@ -948,8 +1026,8 @@ public ResultScanner call() throws IOException {
948
1026
if (scan .getFamilyMap ().keySet () == null
949
1027
|| scan .getFamilyMap ().keySet ().isEmpty ()
950
1028
|| scan .getFamilyMap ().size () > 1 ) {
951
- // In a Scan operation where the family map is greater than 1 or equal to 0,
952
- // we handle this by appending the column family to the qualifier on the client side.
1029
+ // In a Scan operation where the family map is greater than 1 or equal to 0,
1030
+ // we handle this by appending the column family to the qualifier on the client side.
953
1031
// The server can then use this information to filter the appropriate column families and qualifiers.
954
1032
if (!scan .getColumnFamilyTimeRange ().isEmpty ()) {
955
1033
throw new FeatureNotSupportedException ("setColumnFamilyTimeRange is only supported in single column family for now" );
@@ -1464,7 +1542,6 @@ public void close() throws IOException {
1464
1542
if (cleanupPoolOnClose ) {
1465
1543
executePool .shutdown ();
1466
1544
}
1467
- ObTableClientManager .clear ();
1468
1545
}
1469
1546
1470
1547
@ Override
@@ -1514,6 +1591,8 @@ public <R extends Message> void batchCoprocessorService(Descriptors.MethodDescri
1514
1591
@ Override
1515
1592
public void setOperationTimeout (int operationTimeout ) {
1516
1593
this .operationTimeout = operationTimeout ;
1594
+ this .obTableClient .setRuntimeMaxWait (operationTimeout );
1595
+ this .obTableClient .setRuntimeBatchMaxWait (operationTimeout );
1517
1596
this .operationExecuteInPool = this .configuration .getBoolean (
1518
1597
HBASE_CLIENT_OPERATION_EXECUTE_IN_POOL ,
1519
1598
(this .operationTimeout != HConstants .DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT ));
@@ -1834,21 +1913,62 @@ private KeyValue modifyQualifier(Cell original, byte[] newQualifier) {
1834
1913
byte [] value = CellUtil .cloneValue (original );
1835
1914
long timestamp = original .getTimestamp ();
1836
1915
KeyValue .Type type = KeyValue .Type .codeToType (original .getType ().getCode ());
1837
- // Create a new KeyValue with the modified qualifier
1916
+ // Create a new KeyValue with the modified qualifier
1838
1917
return new KeyValue (row , family , newQualifier , timestamp , type , value );
1839
1918
}
1840
1919
1841
1920
private BatchOperation buildBatchOperation (String tableName , List <? extends Row > actions ,
1842
1921
boolean isTableGroup , List <Integer > resultMapSingleOp )
1843
1922
throws FeatureNotSupportedException ,
1844
- IllegalArgumentException {
1923
+ IllegalArgumentException ,
1924
+ IOException {
1845
1925
BatchOperation batch = obTableClient .batchOperation (tableName );
1846
1926
int posInList = -1 ;
1847
1927
int singleOpResultNum ;
1848
1928
for (Row row : actions ) {
1849
1929
singleOpResultNum = 0 ;
1850
1930
posInList ++;
1851
- if (row instanceof Put ) {
1931
+ if (row instanceof Get ) {
1932
+ if (!ObGlobal .isHBaseBatchGetSupport ()) {
1933
+ throw new FeatureNotSupportedException ("server does not support batch get" );
1934
+ }
1935
+ ++singleOpResultNum ;
1936
+ Get get = (Get ) row ;
1937
+ ObTableQuery obTableQuery ;
1938
+ // In a Get operation in ls batch, we need to determine whether the get is a table-group operation or not,
1939
+ // we handle this by appending the column family to the qualifier on the client side.
1940
+ // The server can then use this information to filter the appropriate column families and qualifiers.
1941
+ if ((get .getFamilyMap ().keySet ().isEmpty ()
1942
+ || get .getFamilyMap ().size () > 1 ) &&
1943
+ !get .getColumnFamilyTimeRange ().isEmpty ()) {
1944
+ throw new FeatureNotSupportedException ("setColumnFamilyTimeRange is only supported in single column family for now" );
1945
+ } else if (get .getFamilyMap ().size () == 1 && !get .getColumnFamilyTimeRange ().isEmpty ()) {
1946
+ byte [] family = get .getFamilyMap ().keySet ().iterator ().next ();
1947
+ Map <byte [], TimeRange > colFamTimeRangeMap = get .getColumnFamilyTimeRange ();
1948
+ if (colFamTimeRangeMap .size () > 1 ) {
1949
+ throw new FeatureNotSupportedException ("setColumnFamilyTimeRange is only supported in single column family for now" );
1950
+ } else if (colFamTimeRangeMap .get (family ) == null ) {
1951
+ throw new IllegalArgumentException ("Get family is not matched in ColumnFamilyTimeRange" );
1952
+ } else {
1953
+ TimeRange tr = colFamTimeRangeMap .get (family );
1954
+ get .setTimeRange (tr .getMin (), tr .getMax ());
1955
+ }
1956
+ }
1957
+ NavigableSet <byte []> columnFilters = new TreeSet <>(Bytes .BYTES_COMPARATOR );
1958
+ // in batch get, we need to carry family in qualifier to server even this get is a single-cf operation
1959
+ // because the entire batch may be a multi-cf batch so do not carry family
1960
+ // family in qualifier helps us to know which table to query
1961
+ processColumnFilters (columnFilters , get .getFamilyMap ());
1962
+ obTableQuery = buildObTableQuery (get , columnFilters );
1963
+ ObTableClientQueryImpl query = new ObTableClientQueryImpl (tableName , obTableQuery , obTableClient );
1964
+ try {
1965
+ query .setRowKey (row (colVal ("K" , Bytes .toString (get .getRow ())), colVal ("Q" , null ), colVal ("T" , null )));
1966
+ } catch (Exception e ) {
1967
+ logger .error ("unexpected error occurs when set row key" , e );
1968
+ throw new IOException (e );
1969
+ }
1970
+ batch .addOperation (query );
1971
+ } else if (row instanceof Put ) {
1852
1972
Put put = (Put ) row ;
1853
1973
if (put .isEmpty ()) {
1854
1974
throw new IllegalArgumentException ("No columns to insert for #"
@@ -1882,7 +2002,7 @@ private BatchOperation buildBatchOperation(String tableName, List<? extends Row>
1882
2002
}
1883
2003
} else {
1884
2004
throw new FeatureNotSupportedException (
1885
- "not supported other type in batch yet,only support put and delete" );
2005
+ "not supported other type in batch yet,only support get, put and delete" );
1886
2006
}
1887
2007
resultMapSingleOp .add (singleOpResultNum );
1888
2008
}
@@ -1983,8 +2103,8 @@ public static void checkFamilyViolation(Collection<byte[]> families, boolean che
1983
2103
}
1984
2104
}
1985
2105
1986
- // This method is currently only used for append and increment operations.
1987
- // It restricts these two methods to use multi-column family operations.
2106
+ // This method is currently only used for append and increment operations.
2107
+ // It restricts these two methods to use multi-column family operations.
1988
2108
// Note: After completing operations on multiple column families, they are deleted using the method described above.
1989
2109
public static void checkFamilyViolationForOneFamily (Collection <byte []> families ) {
1990
2110
if (families == null || families .size () == 0 ) {
0 commit comments