[
https://issues.apache.org/jira/browse/HBASE-26688?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Duo Zhang updated HBASE-26688:
------------------------------
Hadoop Flags: Incompatible change,Reviewed (was: Reviewed)
Release Note:
Result#advance with empty cell list will always return false but not raise
NoSuchElementException when called multiple times.
This is a behavior change so it is an 'incompatible change', but since it will
not introduce any compile error and the old behavior is 'broken', so we also
fix it for current release branches.
was:Result#advance with empty cell list will always return false but not
raise NoSuchElementException when called multiple times.
> Threads shared EMPTY_RESULT may lead to unexpected client job down.
> -------------------------------------------------------------------
>
> Key: HBASE-26688
> URL: https://issues.apache.org/jira/browse/HBASE-26688
> Project: HBase
> Issue Type: Bug
> Components: Client
> Reporter: Yutong Xiao
> Assignee: Yutong Xiao
> Priority: Major
> Fix For: 2.5.0, 3.0.0-alpha-3, 2.4.10
>
>
> Currently, we use a pre-created EMPTY_RESULT in the ProtoBuf.util to reduce
> the object creation. But these objects could be shared by multi client
> threads. The Result#cellScannerIndex related methods could throw confusing
> exception and make the client job down. Could refine the logic of these
> methods.
> The precreated objects in ProtoBufUtil.java:
> {code:java}
> private final static Cell[] EMPTY_CELL_ARRAY = new Cell[]{};
> private final static Result EMPTY_RESULT = Result.create(EMPTY_CELL_ARRAY);
> final static Result EMPTY_RESULT_EXISTS_TRUE = Result.create(null, true);
> final static Result EMPTY_RESULT_EXISTS_FALSE = Result.create(null, false);
> private final static Result EMPTY_RESULT_STALE =
> Result.create(EMPTY_CELL_ARRAY, null, true);
> {code}
> Result#advance
> {code:java}
> public boolean advance() {
> if (cells == null) return false;
> cellScannerIndex++;
> if (cellScannerIndex < this.cells.length) {
> return true;
> } else if (cellScannerIndex == this.cells.length) {
> return false;
> }
> // The index of EMPTY_RESULT could be incremented by multi threads and
> throw this exception.
> throw new NoSuchElementException("Cannot advance beyond the last cell");
> }
> {code}
> Result#current
> {code:java}
> public Cell current() {
> if (cells == null
> || cellScannerIndex == INITIAL_CELLSCANNER_INDEX
> || cellScannerIndex >= cells.length)
> return null;
> // Although it is almost impossible,
> // We can arrive here when the client threads share the common reused
> EMPTY_RESULT.
> return this.cells[cellScannerIndex];
> }
> {code}
> In this case, the client can easily got confusing exceptions even if they use
> different connections, tables in different threads.
> We should change the if condition cells == null to isEmpty() to avoid the
> client crashed from these exception.
--
This message was sent by Atlassian Jira
(v8.20.1#820001)