public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {
    if (!isRunning()) {
      return;
    }
    if (LOG.isTraceEnabled()) {
      LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,
        regionNames.size(), isMetaLoaded(),
        regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));
    }

    ServerStateNode serverNode = regionStates.getServerNode(serverName);
    if (serverNode == null) {
      LOG.warn("Got a report from server {} where its server node is null", serverName);
      return;
    }
    serverNode.readLock().lock();
    try {
      if (!serverNode.isInState(ServerState.ONLINE)) {
        LOG.warn("Got a report from a server result in state {}", serverNode);
        return;
      }
    } finally {
      serverNode.readLock().unlock();
    }

    // Track the regionserver reported online regions in memory.
    synchronized (rsReports) {
      rsReports.put(serverName, regionNames);
    }

    if (regionNames.isEmpty()) {
      // nothing to do if we don't have regions
      LOG.trace("no online region found on {}", serverName);
      return;
    }
    if (!isMetaLoaded()) {
      // we are still on startup, skip checking
      return;
    }
    // The Heartbeat tells us of what regions are on the region serve, check the state.
    checkOnlineRegionsReport(serverNode, regionNames);
  }
The master will call this method when the RS send the regionServerReport(). The report will
contains the "online regions". This method will check the the online regions against the
in-memory state of the AM, and we will log a warn message if there is a mismatch. This is
because that there is no fencing between the reportRegionStateTransition method and
regionServerReport method, so there could be race and introduce inconsistency here, but
actually there is no problem.
<p/>
Please see HBASE-21421 and HBASE-21463 for more details.
hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java