use of org.apache.accumulo.core.metadata.TServerInstance in project accumulo by apache.
the class TabletGroupWatcher method hostUnassignedTablet.
private void hostUnassignedTablet(TabletLists tLists, KeyExtent tablet, TServerInstance location) {
// maybe it's a finishing migration
TServerInstance dest = manager.migrations.get(tablet);
if (dest != null) {
// if destination is still good, assign it
if (tLists.destinations.containsKey(dest)) {
tLists.assignments.add(new Assignment(tablet, dest));
} else {
// get rid of this migration
manager.migrations.remove(tablet);
tLists.unassigned.put(tablet, location);
}
} else {
tLists.unassigned.put(tablet, location);
}
}
use of org.apache.accumulo.core.metadata.TServerInstance in project accumulo by apache.
the class TabletGroupWatcher method run.
@Override
public void run() {
int[] oldCounts = new int[TabletState.values().length];
EventCoordinator.Listener eventListener = this.manager.nextEvent.getListener();
WalStateManager wals = new WalStateManager(manager.getContext());
while (manager.stillManager()) {
// slow things down a little, otherwise we spam the logs when there are many wake-up events
sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
int totalUnloaded = 0;
int unloaded = 0;
ClosableIterator<TabletLocationState> iter = null;
try {
Map<TableId, MergeStats> mergeStatsCache = new HashMap<>();
Map<TableId, MergeStats> currentMerges = new HashMap<>();
for (MergeInfo merge : manager.merges()) {
if (merge.getExtent() != null) {
currentMerges.put(merge.getExtent().tableId(), new MergeStats(merge));
}
}
// Get the current status for the current list of tservers
SortedMap<TServerInstance, TabletServerStatus> currentTServers = new TreeMap<>();
for (TServerInstance entry : manager.tserverSet.getCurrentServers()) {
currentTServers.put(entry, manager.tserverStatus.get(entry));
}
if (currentTServers.isEmpty()) {
eventListener.waitForEvents(Manager.TIME_TO_WAIT_BETWEEN_SCANS);
synchronized (this) {
lastScanServers = Collections.emptySortedSet();
}
continue;
}
TabletLists tLists = new TabletLists(manager, currentTServers);
ManagerState managerState = manager.getManagerState();
int[] counts = new int[TabletState.values().length];
stats.begin();
// Walk through the tablets in our store, and work tablets
// towards their goal
iter = store.iterator();
while (iter.hasNext()) {
TabletLocationState tls = iter.next();
if (tls == null) {
continue;
}
// ignore entries for tables that do not exist in zookeeper
if (manager.getTableManager().getTableState(tls.extent.tableId()) == null)
continue;
// Don't overwhelm the tablet servers with work
if (tLists.unassigned.size() + unloaded > Manager.MAX_TSERVER_WORK_CHUNK * currentTServers.size()) {
flushChanges(tLists, wals);
tLists.reset();
unloaded = 0;
eventListener.waitForEvents(Manager.TIME_TO_WAIT_BETWEEN_SCANS);
}
TableId tableId = tls.extent.tableId();
TableConfiguration tableConf = manager.getContext().getTableConfiguration(tableId);
MergeStats mergeStats = mergeStatsCache.computeIfAbsent(tableId, k -> {
var mStats = currentMerges.get(k);
return mStats != null ? mStats : new MergeStats(new MergeInfo());
});
TabletGoalState goal = manager.getGoalState(tls, mergeStats.getMergeInfo());
TServerInstance location = tls.getLocation();
TabletState state = tls.getState(currentTServers.keySet());
TabletLogger.missassigned(tls.extent, goal.toString(), state.toString(), tls.future, tls.current, tls.walogs.size());
stats.update(tableId, state);
mergeStats.update(tls.extent, state, tls.chopped, !tls.walogs.isEmpty());
sendChopRequest(mergeStats.getMergeInfo(), state, tls);
sendSplitRequest(mergeStats.getMergeInfo(), state, tls);
// Always follow through with assignments
if (state == TabletState.ASSIGNED) {
goal = TabletGoalState.HOSTED;
}
// if we are shutting down all the tabletservers, we have to do it in order
if ((goal == TabletGoalState.SUSPENDED && state == TabletState.HOSTED) && manager.serversToShutdown.equals(currentTServers.keySet())) {
if (dependentWatcher != null && dependentWatcher.assignedOrHosted() > 0) {
goal = TabletGoalState.HOSTED;
}
}
if (goal == TabletGoalState.HOSTED) {
if ((state != TabletState.HOSTED && !tls.walogs.isEmpty()) && manager.recoveryManager.recoverLogs(tls.extent, tls.walogs))
continue;
switch(state) {
case HOSTED:
if (location.equals(manager.migrations.get(tls.extent)))
manager.migrations.remove(tls.extent);
break;
case ASSIGNED_TO_DEAD_SERVER:
hostDeadTablet(tLists, tls, location, wals);
break;
case SUSPENDED:
hostSuspendedTablet(tLists, tls, location, tableConf);
break;
case UNASSIGNED:
hostUnassignedTablet(tLists, tls.extent, location);
break;
case ASSIGNED:
// Send another reminder
tLists.assigned.add(new Assignment(tls.extent, tls.future));
break;
}
} else {
switch(state) {
case SUSPENDED:
// Request a move to UNASSIGNED, so as to allow balancing to continue.
tLists.suspendedToGoneServers.add(tls);
cancelOfflineTableMigrations(tls.extent);
break;
case UNASSIGNED:
cancelOfflineTableMigrations(tls.extent);
break;
case ASSIGNED_TO_DEAD_SERVER:
unassignDeadTablet(tLists, tls, wals);
break;
case HOSTED:
TServerConnection client = manager.tserverSet.getConnection(location);
if (client != null) {
client.unloadTablet(manager.managerLock, tls.extent, goal.howUnload(), manager.getSteadyTime());
unloaded++;
totalUnloaded++;
} else {
Manager.log.warn("Could not connect to server {}", location);
}
break;
case ASSIGNED:
break;
}
}
counts[state.ordinal()]++;
}
flushChanges(tLists, wals);
// provide stats after flushing changes to avoid race conditions w/ delete table
stats.end(managerState);
// Report changes
for (TabletState state : TabletState.values()) {
int i = state.ordinal();
if (counts[i] > 0 && counts[i] != oldCounts[i]) {
manager.nextEvent.event("[%s]: %d tablets are %s", store.name(), counts[i], state.name());
}
}
Manager.log.debug(String.format("[%s]: scan time %.2f seconds", store.name(), stats.getScanTime() / 1000.));
oldCounts = counts;
if (totalUnloaded > 0) {
manager.nextEvent.event("[%s]: %d tablets unloaded", store.name(), totalUnloaded);
}
updateMergeState(mergeStatsCache);
synchronized (this) {
lastScanServers = ImmutableSortedSet.copyOf(currentTServers.keySet());
}
if (manager.tserverSet.getCurrentServers().equals(currentTServers.keySet())) {
Manager.log.debug(String.format("[%s] sleeping for %.2f seconds", store.name(), Manager.TIME_TO_WAIT_BETWEEN_SCANS / 1000.));
eventListener.waitForEvents(Manager.TIME_TO_WAIT_BETWEEN_SCANS);
} else {
Manager.log.info("Detected change in current tserver set, re-running state machine.");
}
} catch (Exception ex) {
Manager.log.error("Error processing table state for store " + store.name(), ex);
if (ex.getCause() != null && ex.getCause() instanceof BadLocationStateException) {
repairMetadata(((BadLocationStateException) ex.getCause()).getEncodedEndRow());
} else {
sleepUninterruptibly(Manager.WAIT_BETWEEN_ERRORS, TimeUnit.MILLISECONDS);
}
} finally {
if (iter != null) {
try {
iter.close();
} catch (IOException ex) {
Manager.log.warn("Error closing TabletLocationState iterator: " + ex, ex);
}
}
}
}
}
use of org.apache.accumulo.core.metadata.TServerInstance in project accumulo by apache.
the class TabletGroupWatcher method getAssignmentsFromBalancer.
private void getAssignmentsFromBalancer(TabletLists tLists, Map<KeyExtent, TServerInstance> unassigned) {
if (!tLists.currentTServers.isEmpty()) {
Map<KeyExtent, TServerInstance> assignedOut = new HashMap<>();
manager.getAssignments(tLists.currentTServers, unassigned, assignedOut);
for (Entry<KeyExtent, TServerInstance> assignment : assignedOut.entrySet()) {
if (unassigned.containsKey(assignment.getKey())) {
if (assignment.getValue() != null) {
if (!tLists.currentTServers.containsKey(assignment.getValue())) {
Manager.log.warn("balancer assigned {} to a tablet server that is not current {} ignoring", assignment.getKey(), assignment.getValue());
continue;
}
tLists.assignments.add(new Assignment(assignment.getKey(), assignment.getValue()));
}
} else {
Manager.log.warn("{} load balancer assigning tablet that was not nominated for assignment {}", store.name(), assignment.getKey());
}
}
if (!unassigned.isEmpty() && assignedOut.isEmpty())
Manager.log.warn("Load balancer failed to assign any tablets");
}
}
use of org.apache.accumulo.core.metadata.TServerInstance in project accumulo by apache.
the class TabletGroupWatcher method hostDeadTablet.
private void hostDeadTablet(TabletLists tLists, TabletLocationState tls, TServerInstance location, WalStateManager wals) throws WalMarkerException {
tLists.assignedToDeadServers.add(tls);
if (location.equals(manager.migrations.get(tls.extent)))
manager.migrations.remove(tls.extent);
TServerInstance tserver = tls.futureOrCurrent();
if (!tLists.logsForDeadServers.containsKey(tserver)) {
tLists.logsForDeadServers.put(tserver, wals.getWalsInUse(tserver));
}
}
use of org.apache.accumulo.core.metadata.TServerInstance in project accumulo by apache.
the class GarbageCollectWriteAheadLogs method collect.
public void collect(GCStatus status) {
try {
long count;
long fileScanStop;
Map<TServerInstance, Set<UUID>> logsByServer;
Map<UUID, Pair<WalState, Path>> logsState;
Map<UUID, Path> recoveryLogs;
Span span = TraceUtil.startSpan(this.getClass(), "getCandidates");
try (Scope scope = span.makeCurrent()) {
status.currentLog.started = System.currentTimeMillis();
recoveryLogs = getSortedWALogs();
logsByServer = new HashMap<>();
logsState = new HashMap<>();
// Scan for log file info first: the order is important
// Consider:
// * get live servers
// * new server gets a lock, creates a log
// * get logs
// * the log appears to belong to a dead server
count = getCurrent(logsByServer, logsState);
fileScanStop = System.currentTimeMillis();
log.info(String.format("Fetched %d files for %d servers in %.2f seconds", count, logsByServer.size(), (fileScanStop - status.currentLog.started) / 1000.));
status.currentLog.candidates = count;
} catch (Exception e) {
TraceUtil.setException(span, e, true);
throw e;
} finally {
span.end();
}
// now it's safe to get the liveServers
liveServers.scanServers();
Set<TServerInstance> currentServers = liveServers.getCurrentServers();
Map<UUID, TServerInstance> uuidToTServer;
Span span2 = TraceUtil.startSpan(this.getClass(), "removeEntriesInUse");
try (Scope scope = span2.makeCurrent()) {
uuidToTServer = removeEntriesInUse(logsByServer, currentServers, logsState, recoveryLogs);
count = uuidToTServer.size();
} catch (Exception ex) {
log.error("Unable to scan metadata table", ex);
TraceUtil.setException(span2, ex, false);
return;
} finally {
span2.end();
}
long logEntryScanStop = System.currentTimeMillis();
log.info(String.format("%d log entries scanned in %.2f seconds", count, (logEntryScanStop - fileScanStop) / 1000.));
Span span3 = TraceUtil.startSpan(this.getClass(), "removeReplicationEntries");
try (Scope scope = span3.makeCurrent()) {
count = removeReplicationEntries(uuidToTServer);
} catch (Exception ex) {
log.error("Unable to scan replication table", ex);
TraceUtil.setException(span3, ex, false);
return;
} finally {
span3.end();
}
long replicationEntryScanStop = System.currentTimeMillis();
log.info(String.format("%d replication entries scanned in %.2f seconds", count, (replicationEntryScanStop - logEntryScanStop) / 1000.));
long removeStop;
Span span4 = TraceUtil.startSpan(this.getClass(), "removeFiles");
try (Scope scope = span4.makeCurrent()) {
logsState.keySet().retainAll(uuidToTServer.keySet());
count = removeFiles(logsState.values(), status);
removeStop = System.currentTimeMillis();
log.info(String.format("%d total logs removed from %d servers in %.2f seconds", count, logsByServer.size(), (removeStop - logEntryScanStop) / 1000.));
count = removeFiles(recoveryLogs.values());
log.info("{} recovery logs removed", count);
} catch (Exception e) {
TraceUtil.setException(span4, e, true);
throw e;
} finally {
span4.end();
}
Span span5 = TraceUtil.startSpan(this.getClass(), "removeMarkers");
try (Scope scope = span5.makeCurrent()) {
count = removeTabletServerMarkers(uuidToTServer, logsByServer, currentServers);
long removeMarkersStop = System.currentTimeMillis();
log.info(String.format("%d markers removed in %.2f seconds", count, (removeMarkersStop - removeStop) / 1000.));
} catch (Exception e) {
TraceUtil.setException(span5, e, true);
throw e;
} finally {
span5.end();
}
status.currentLog.finished = removeStop;
status.lastLog = status.currentLog;
status.currentLog = new GcCycleStats();
} catch (Exception e) {
log.error("exception occurred while garbage collecting write ahead logs", e);
}
}
Aggregations