Skip to content

HBASE-30353 Prevent split parent from being re-opened after master failover - #267

Draft
tanyastickles wants to merge 6 commits into
hubspot-2.6from
HBASE-30353-split-parent-assign-guard
Draft

tanyastickles wants to merge 6 commits into
hubspot-2.6from
HBASE-30353-split-parent-assign-guard

Conversation

@tanyastickles

@tanyastickles tanyastickles commented Sep 11, 2026

Copy link
Copy Markdown

Description

Upstream Jira: HBASE-30353
Internal Issue: https://github.com/HubSpotEngineering/HBasePlanning/issues/2627

We ran into a bug where if the HMaster fails over after a region is split, a split parent can come online again. After a region split, a split parent should never be opened.

Step by step:

  • In memory, the HMaster tracks the state=SPLIT. In the metadata, it writes split=true, offline=true, state=CLOSED.
  • After HMaster failover, the HMaster reconstructs the region metadata with state=CLOSED. The parent region ends up looking like an ordinary stuck in closing region instead of a split parent.

BRAVE

Backwards Compatibility

Rollout and Rollback Plan

Automated Testing

Verification

Expect Dependencies to Fail

REVIEWERS: Please review both the code changes and the answers above, and validate that they match the expectations for BRAVE

🤖 Generated with Claude Code

Tanya Stickles and others added 6 commits September 11, 2026 14:59
…ilover

After a split, MetaTableAccessor.splitRegion writes split=true/offline=true
into info:regioninfo but never updates info:state from CLOSED (left by the
pre-split unassign). On failover, loadMeta rebuilds the RegionStateNode with
state=CLOSED, so preTransitCheck accepted the parent for assign because CLOSED
is in STATES_EXPECTED_ON_ASSIGN. The parent could then be opened, archiving
store files the daughters still reference via HFileLinks.

Fix: add RegionStateNode.checkNotRetired(), which throws
DoNotRetryRegionException when isSplit() is true. Call it from
preTransitCheck before any external assign can proceed, covering both
the live state (state=SPLIT) and the post-failover state
(regionInfo.isSplit()=true, state=CLOSED).

Adds TestSplitParentAssignment to reproduce the exact post-failover
precondition by deleting the existing RSN and re-creating it from a
split=true RegionInfo with state=CLOSED, then asserting that assign()
throws DoNotRetryRegionException.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…h; add unit tests

- Add checkNotRetired() before the override branch in createAssignProcedure
  so HBCK2 and other override=true callers cannot assign a split parent
  (previously only preTransitCheck covered the override=false path)
- Port two mock-based unit tests from the alternate branch into
  TestAssignmentManager: CLOSED-after-failover and SPLIT-state cases,
  each asserting both assign() throws and createOneAssignProcedure returns null

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follow WET guidance: inline the isSplit() check directly in
AssignmentManager at both call sites instead of abstracting it into
RegionStateNode.checkNotRetired().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ass name)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant