Skip to content

Commit 548f503

Browse files
committed
Merge branch 'master' into secondary_part-merge-master
2 parents cead59b + cf09ce6 commit 548f503

16 files changed

+289
-211
lines changed

src/main/java/com/alipay/oceanbase/hbase/OHTable.java

Lines changed: 70 additions & 134 deletions
Large diffs are not rendered by default.

src/main/java/com/alipay/oceanbase/hbase/OHTablePool.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.protobuf.Service;
2727
import com.google.protobuf.ServiceException;
2828
import org.apache.hadoop.conf.Configuration;
29+
import org.apache.hadoop.hbase.HBaseConfiguration;
2930
import org.apache.hadoop.hbase.HTableDescriptor;
3031
import org.apache.hadoop.hbase.TableName;
3132
import org.apache.hadoop.hbase.client.*;
@@ -67,7 +68,7 @@ public class OHTablePool implements Closeable {
6768
* Default Constructor. Default HBaseConfiguration and no limit on pool size.
6869
*/
6970
public OHTablePool() {
70-
this(new Configuration(), Integer.MAX_VALUE);
71+
this(HBaseConfiguration.create(), Integer.MAX_VALUE);
7172
}
7273

7374
/**

src/main/java/com/alipay/oceanbase/hbase/constants/OHConstants.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,6 @@ public final class OHConstants {
143143

144144
public static final String MAX_KEYVALUE_SIZE_KEY = "hbase.client.keyvalue.maxsize";
145145

146-
public static final String HBASE_HTABLE_PUT_WRITE_BUFFER_CHECK = "hbase.htable.put.write.buffer.check";
147-
148-
public static final int DEFAULT_HBASE_HTABLE_PUT_WRITE_BUFFER_CHECK = 10;
149-
150146
public static final long WRITE_BUFFER_SIZE_DEFAULT = 2097152L;
151147

152148
public static final int MAX_KEYVALUE_SIZE_DEFAULT = -1;

src/main/java/com/alipay/oceanbase/hbase/util/BatchError.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/*-
2+
* #%L
3+
* com.oceanbase:obkv-hbase-client
4+
* %%
5+
* Copyright (C) 2022 - 2025 OceanBase Group
6+
* %%
7+
* OBKV HBase Client Framework is licensed under Mulan PSL v2.
8+
* You can use this software according to the terms and conditions of the Mulan PSL v2.
9+
* You may obtain a copy of Mulan PSL v2 at:
10+
* http://license.coscl.org.cn/MulanPSL2
11+
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12+
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13+
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14+
* See the Mulan PSL v2 for more details.
15+
* #L%
16+
*/
17+
118
package com.alipay.oceanbase.hbase.util;
219

320
import org.apache.hadoop.hbase.ServerName;

src/main/java/com/alipay/oceanbase/hbase/util/OHBaseFuncUtils.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ public static byte[][] extractFamilyFromQualifier(byte[] qualifier) throws Excep
3535
throw new RuntimeException("Cannot get family name");
3636
}
3737
byte[] family = Arrays.copyOfRange(qualifier, 0, familyLen);
38-
int qualifierLen = qualifier.length - familyLen - 1;
39-
if (qualifierLen <= 0) {
40-
throw new RuntimeException("Cannot get qualifier name");
41-
}
4238
byte[] newQualifier = Arrays.copyOfRange(qualifier, familyLen + 1, qualifier.length);
4339
return new byte[][] { family, newQualifier };
4440
}

src/main/java/com/alipay/oceanbase/hbase/util/OHBufferedMutatorImpl.java

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
package com.alipay.oceanbase.hbase.util;
1919

2020
import com.alipay.oceanbase.hbase.OHTable;
21-
import com.google.common.annotations.VisibleForTesting;
21+
import com.alipay.oceanbase.rpc.exception.ObTableUnexpectedException;
22+
import com.alipay.oceanbase.rpc.protocol.payload.impl.execute.ObTableBatchOperation;
2223
import org.apache.hadoop.classification.InterfaceAudience;
2324
import org.apache.hadoop.conf.Configuration;
25+
import org.apache.hadoop.hbase.KeyValue;
2426
import org.apache.hadoop.hbase.TableName;
2527
import org.apache.hadoop.hbase.client.*;
2628
import org.slf4j.Logger;
@@ -31,7 +33,9 @@
3133
import java.util.concurrent.ExecutorService;
3234
import java.util.concurrent.TimeUnit;
3335
import java.util.concurrent.atomic.AtomicLong;
34-
import static com.alipay.oceanbase.rpc.util.TableClientLoggerFactory.LCD;
36+
37+
import static com.alipay.oceanbase.hbase.util.TableHBaseLoggerFactory.LCD;
38+
import static com.alipay.oceanbase.rpc.ObGlobal.*;
3539

3640
@InterfaceAudience.Private
3741
public class OHBufferedMutatorImpl implements BufferedMutator {
@@ -40,13 +44,11 @@ public class OHBufferedMutatorImpl implements BufferedMutator {
4044

4145
private final ExceptionListener listener;
4246

43-
private final OHTable ohTable;
4447
private final TableName tableName;
4548
private volatile Configuration conf;
4649

47-
@VisibleForTesting
50+
private OHTable ohTable;
4851
final ConcurrentLinkedQueue<Mutation> asyncWriteBuffer = new ConcurrentLinkedQueue<Mutation>();
49-
@VisibleForTesting
5052
AtomicLong currentAsyncBufferSize = new AtomicLong(0);
5153

5254
private long writeBufferSize;
@@ -55,9 +57,11 @@ public class OHBufferedMutatorImpl implements BufferedMutator {
5557
private final ExecutorService pool;
5658
private int rpcTimeout;
5759
private int operationTimeout;
60+
private static final long OB_VERSION_4_2_5_1 = calcVersion(4, (short) 2,
61+
(byte) 5, (byte) 1);
5862

59-
public OHBufferedMutatorImpl(OHConnectionImpl ohConnection, BufferedMutatorParams params)
60-
throws IOException {
63+
public OHBufferedMutatorImpl(OHConnectionImpl ohConnection, BufferedMutatorParams params,
64+
OHTable ohTable) throws IOException {
6165
if (ohConnection == null || ohConnection.isClosed()) {
6266
throw new IllegalArgumentException("Connection is null or closed.");
6367
}
@@ -77,7 +81,38 @@ public OHBufferedMutatorImpl(OHConnectionImpl ohConnection, BufferedMutatorParam
7781
.getMaxKeyValueSize() : connectionConfig.getMaxKeyValueSize();
7882

7983
// create an OHTable object to do batch work
80-
this.ohTable = new OHTable(tableName, ohConnection, connectionConfig, pool);
84+
if (ohTable != null) {
85+
this.ohTable = ohTable;
86+
} else {
87+
this.ohTable = new OHTable(tableName, ohConnection, connectionConfig, pool);
88+
}
89+
}
90+
91+
/**
92+
* only used for OHTable get bufferedMutator
93+
* */
94+
public OHBufferedMutatorImpl(Configuration conf, BufferedMutatorParams params, OHTable ohTable)
95+
throws IOException {
96+
// create an OHTable object to do batch work
97+
if (ohTable == null) {
98+
throw new ObTableUnexpectedException("The ohTable is null.");
99+
}
100+
this.ohTable = ohTable;
101+
// init params in OHBufferedMutatorImpl
102+
this.tableName = params.getTableName();
103+
this.conf = conf;
104+
this.listener = params.getListener();
105+
106+
OHConnectionConfiguration connectionConfig = new OHConnectionConfiguration(conf);
107+
this.pool = params.getPool();
108+
this.rpcTimeout = connectionConfig.getRpcTimeout();
109+
this.operationTimeout = connectionConfig.getOperationTimeout();
110+
111+
this.writeBufferSize = params.getWriteBufferSize() != OHConnectionImpl.BUFFERED_PARAM_UNSET ? params
112+
.getWriteBufferSize() : connectionConfig.getWriteBufferSize();
113+
this.maxKeyValueSize = params.getMaxKeyValueSize() != OHConnectionImpl.BUFFERED_PARAM_UNSET ? params
114+
.getMaxKeyValueSize() : connectionConfig.getMaxKeyValueSize();
115+
81116
}
82117

83118
@Override
@@ -119,14 +154,12 @@ public void mutate(List<? extends Mutation> mutations) throws IOException {
119154
validateOperation(m);
120155
toAddSize += m.heapSize();
121156
}
122-
123157
currentAsyncBufferSize.addAndGet(toAddSize);
124158
asyncWriteBuffer.addAll(mutations);
125159

126160
if (currentAsyncBufferSize.get() > writeBufferSize) {
127-
execute(false);
161+
batchExecute(false);
128162
}
129-
130163
}
131164

132165
/**
@@ -142,10 +175,18 @@ private void validateOperation(Mutation mt) throws IllegalArgumentException {
142175
}
143176
if (mt instanceof Put) {
144177
// family empty check is in validatePut
145-
HTable.validatePut((Put) mt, maxKeyValueSize);
146-
OHTable.checkFamilyViolation(mt.getFamilyMap().keySet(), true);
178+
OHTable.validatePut((Put) mt, maxKeyValueSize);
179+
if (isMultiFamilySupport()) {
180+
OHTable.checkFamilyViolation(mt.getFamilyMap().keySet(), true);
181+
} else {
182+
OHTable.checkFamilyViolationForOneFamily(mt.getFamilyMap().keySet());
183+
}
147184
} else {
148-
OHTable.checkFamilyViolation(mt.getFamilyMap().keySet(), false);
185+
if (isMultiFamilySupport()) {
186+
OHTable.checkFamilyViolation(mt.getFamilyMap().keySet(), false);
187+
} else {
188+
OHTable.checkFamilyViolationForOneFamily(mt.getFamilyMap().keySet());
189+
}
149190
}
150191
}
151192

@@ -156,7 +197,7 @@ private void validateOperation(Mutation mt) throws IllegalArgumentException {
156197
* @param flushAll - if true, sends all the writes and wait for all of them to finish before
157198
* returning.
158199
*/
159-
private void execute(boolean flushAll) throws IOException {
200+
private void batchExecute(boolean flushAll) throws IOException {
160201
LinkedList<Mutation> execBuffer = new LinkedList<>();
161202
long dequeuedSize = 0L;
162203
try {
@@ -172,19 +213,16 @@ private void execute(boolean flushAll) throws IOException {
172213
if (execBuffer.isEmpty()) {
173214
return;
174215
}
175-
ohTable.batch(execBuffer);
216+
Object[] results = new Object[execBuffer.size()];
217+
ohTable.batch(execBuffer, results);
176218
// if commit all successfully, clean execBuffer
177219
execBuffer.clear();
178220
} catch (Exception ex) {
179-
LOGGER.error(LCD.convert("01-00026"), ex);
221+
// do not recollect error operations, notify outside
222+
LOGGER.error("error happens: table name = ", tableName.getNameAsString(), ex);
180223
if (ex.getCause() instanceof RetriesExhaustedWithDetailsException) {
181-
LOGGER.error(tableName + ": One or more of the operations have failed after retries.");
224+
LOGGER.error(tableName.getNameAsString() + ": One or more of the operations have failed after retries.", ex);
182225
RetriesExhaustedWithDetailsException retryException = (RetriesExhaustedWithDetailsException) ex.getCause();
183-
// recollect mutations
184-
execBuffer.clear();
185-
for (int i = 0; i < retryException.getNumExceptions(); ++i) {
186-
execBuffer.add((Mutation) retryException.getRow(i));
187-
}
188226
if (listener != null) {
189227
listener.onException(retryException, this);
190228
} else {
@@ -194,12 +232,6 @@ private void execute(boolean flushAll) throws IOException {
194232
LOGGER.error("Errors unrelated to operations occur during mutation operation", ex);
195233
throw ex;
196234
}
197-
} finally {
198-
for (Mutation mutation : execBuffer) {
199-
long size = mutation.heapSize();
200-
currentAsyncBufferSize.addAndGet(size);
201-
asyncWriteBuffer.add(mutation);
202-
}
203235
}
204236
}
205237

@@ -209,7 +241,7 @@ public void close() throws IOException {
209241
return;
210242
}
211243
try {
212-
execute(true);
244+
batchExecute(true);
213245
} finally {
214246
// the pool in ObTableClient will be shut down too
215247
this.pool.shutdown();
@@ -234,13 +266,21 @@ public void setWriteBufferSize(long writeBufferSize) throws IOException {
234266
}
235267
}
236268

269+
/**
270+
* Only 4_2_5 BP1 - 4_3_0 and after 4_3_4 support multi-cf
271+
* */
272+
boolean isMultiFamilySupport() {
273+
return (OB_VERSION >= OB_VERSION_4_2_5_1 && OB_VERSION < OB_VERSION_4_3_0_0)
274+
|| (OB_VERSION >= OB_VERSION_4_3_4_0);
275+
}
276+
237277
/**
238278
* Force to commit all operations
239279
* do not care whether the pool is shut down or this BufferedMutator is closed
240280
*/
241281
@Override
242282
public void flush() throws IOException {
243-
execute(true);
283+
batchExecute(true);
244284
}
245285

246286
@Override
@@ -258,6 +298,10 @@ public void setOperationTimeout(int operationTimeout) {
258298
this.ohTable.setOperationTimeout(operationTimeout);
259299
}
260300

301+
public long getCurrentBufferSize() {
302+
return currentAsyncBufferSize.get();
303+
}
304+
261305
@Deprecated
262306
public List<Row> getWriteBuffer() {
263307
return Arrays.asList(asyncWriteBuffer.toArray(new Row[0]));

src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionImpl.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ public BufferedMutator getBufferedMutator(TableName tableName) throws IOExceptio
126126

127127
@Override
128128
public BufferedMutator getBufferedMutator(BufferedMutatorParams params) throws IOException {
129+
return getBufferedMutator(params, null);
130+
}
131+
132+
public BufferedMutator getBufferedMutator(BufferedMutatorParams params, OHTable ohTable)
133+
throws IOException {
129134
if (params.getTableName() == null) {
130135
throw new IllegalArgumentException("TableName cannot be null.");
131136
}
@@ -138,7 +143,7 @@ public BufferedMutator getBufferedMutator(BufferedMutatorParams params) throws I
138143
if (params.getMaxKeyValueSize() == BUFFERED_PARAM_UNSET) {
139144
params.maxKeyValueSize(connectionConfig.getMaxKeyValueSize());
140145
}
141-
return new OHBufferedMutatorImpl(this, params);
146+
return new OHBufferedMutatorImpl(this, params, ohTable);
142147
}
143148

144149
@Override

src/main/java/com/alipay/oceanbase/hbase/util/OHTableFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.alipay.oceanbase.hbase.OHTablePool;
2222
import org.apache.hadoop.classification.InterfaceAudience;
2323
import org.apache.hadoop.conf.Configuration;
24+
import org.apache.hadoop.hbase.HBaseConfiguration;
2425
import org.apache.hadoop.hbase.client.HTableFactory;
2526
import org.apache.hadoop.hbase.client.HTableInterface;
2627
import org.apache.hadoop.hbase.util.Bytes;
@@ -170,7 +171,7 @@ private Configuration adjustConfiguration(Configuration configuration, String ta
170171
}
171172

172173
private Configuration copyConfiguration(Configuration origin) {
173-
Configuration copy = new Configuration();
174+
Configuration copy = HBaseConfiguration.create();
174175

175176
for (Map.Entry<String, String> entry : origin) {
176177
copy.set(entry.getKey(), entry.getValue());

src/test/java/com/alipay/oceanbase/hbase/HTableMultiCFTestBase.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,38 @@ public void testMultiColumnFamilyGet() throws Exception {
15221522
}
15231523
}
15241524
assertEquals(5, keyValues.length);
1525+
1526+
// test multi-cf get checkExistenceOnly
1527+
Delete delKey1 = new Delete(toBytes("Key1"));
1528+
multiCfHTable.delete(delKey1);
1529+
get = new Get(toBytes("Key1"));
1530+
Result allKey1Result = multiCfHTable.get(get);
1531+
Assert.assertEquals(0, allKey1Result.size());
1532+
1533+
boolean exist = multiCfHTable.exists(get);
1534+
assertFalse(exist);
1535+
Put put = new Put(toBytes("Key1"));
1536+
put.add(family1, family1_column1, family1_value);
1537+
multiCfHTable.put(put);
1538+
exist = multiCfHTable.exists(get);
1539+
assertTrue(exist);
1540+
1541+
// test existsAll
1542+
multiCfHTable.delete(delKey1);
1543+
allKey1Result = multiCfHTable.get(get);
1544+
Assert.assertEquals(0, allKey1Result.size());
1545+
1546+
get = new Get(toBytes("Key0"));
1547+
get2 = new Get(toBytes("Key1"));
1548+
get3 = new Get(toBytes("Key2"));
1549+
ArrayList<Get> gets = new ArrayList<>();
1550+
gets.add(get);
1551+
gets.add(get2);
1552+
gets.add(get3);
1553+
boolean[] exists = multiCfHTable.existsAll(gets);
1554+
Assert.assertTrue(exists[0]);
1555+
Assert.assertFalse(exists[1]);
1556+
Assert.assertTrue(exists[2]);
15251557
}
15261558

15271559
@Test

0 commit comments

Comments
 (0)