Search in sources :

Example 71 with TServerInstance

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);
    }
}
Also used : Assignment(org.apache.accumulo.server.manager.state.Assignment) TServerInstance(org.apache.accumulo.core.metadata.TServerInstance)

Example 72 with TServerInstance

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);
                }
            }
        }
    }
}
Also used : TableId(org.apache.accumulo.core.data.TableId) MergeInfo(org.apache.accumulo.server.manager.state.MergeInfo) HashMap(java.util.HashMap) TabletGoalState(org.apache.accumulo.manager.Manager.TabletGoalState) BadLocationStateException(org.apache.accumulo.core.metadata.TabletLocationState.BadLocationStateException) Assignment(org.apache.accumulo.server.manager.state.Assignment) ManagerState(org.apache.accumulo.core.manager.thrift.ManagerState) TabletLocationState(org.apache.accumulo.core.metadata.TabletLocationState) TabletServerStatus(org.apache.accumulo.core.master.thrift.TabletServerStatus) TableConfiguration(org.apache.accumulo.server.conf.TableConfiguration) IOException(java.io.IOException) TreeMap(java.util.TreeMap) TServerInstance(org.apache.accumulo.core.metadata.TServerInstance) TableNotFoundException(org.apache.accumulo.core.client.TableNotFoundException) DistributedStoreException(org.apache.accumulo.server.manager.state.DistributedStoreException) MutationsRejectedException(org.apache.accumulo.core.client.MutationsRejectedException) NotServingTabletException(org.apache.accumulo.core.tabletserver.thrift.NotServingTabletException) WalMarkerException(org.apache.accumulo.server.log.WalStateManager.WalMarkerException) BadLocationStateException(org.apache.accumulo.core.metadata.TabletLocationState.BadLocationStateException) TException(org.apache.thrift.TException) IOException(java.io.IOException) AccumuloException(org.apache.accumulo.core.client.AccumuloException) TServerConnection(org.apache.accumulo.server.manager.LiveTServerSet.TServerConnection) TabletState(org.apache.accumulo.core.metadata.TabletState) WalStateManager(org.apache.accumulo.server.log.WalStateManager) MergeStats(org.apache.accumulo.manager.state.MergeStats)

Example 73 with TServerInstance

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");
    }
}
Also used : Assignment(org.apache.accumulo.server.manager.state.Assignment) HashMap(java.util.HashMap) KeyExtent(org.apache.accumulo.core.dataImpl.KeyExtent) TServerInstance(org.apache.accumulo.core.metadata.TServerInstance)

Example 74 with TServerInstance

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));
    }
}
Also used : TServerInstance(org.apache.accumulo.core.metadata.TServerInstance)

Example 75 with TServerInstance

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);
    }
}
Also used : Path(org.apache.hadoop.fs.Path) HashSet(java.util.HashSet) LiveTServerSet(org.apache.accumulo.server.manager.LiveTServerSet) Set(java.util.Set) GcCycleStats(org.apache.accumulo.core.gc.thrift.GcCycleStats) Span(io.opentelemetry.api.trace.Span) TServerInstance(org.apache.accumulo.core.metadata.TServerInstance) TableNotFoundException(org.apache.accumulo.core.client.TableNotFoundException) WalMarkerException(org.apache.accumulo.server.log.WalStateManager.WalMarkerException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) Scope(io.opentelemetry.context.Scope) UUID(java.util.UUID) Pair(org.apache.accumulo.core.util.Pair)

Aggregations

TServerInstance (org.apache.accumulo.core.metadata.TServerInstance)89 KeyExtent (org.apache.accumulo.core.dataImpl.KeyExtent)32 ArrayList (java.util.ArrayList)31 Test (org.junit.Test)30 HashMap (java.util.HashMap)21 ServerContext (org.apache.accumulo.server.ServerContext)18 TabletLocationState (org.apache.accumulo.core.metadata.TabletLocationState)17 HostAndPort (org.apache.accumulo.core.util.HostAndPort)14 HashSet (java.util.HashSet)13 TabletServerStatus (org.apache.accumulo.core.master.thrift.TabletServerStatus)13 TableId (org.apache.accumulo.core.data.TableId)12 AccumuloConfiguration (org.apache.accumulo.core.conf.AccumuloConfiguration)11 List (java.util.List)10 LiveTServerSet (org.apache.accumulo.server.manager.LiveTServerSet)10 TException (org.apache.thrift.TException)10 TreeMap (java.util.TreeMap)9 UUID (java.util.UUID)9 TreeSet (java.util.TreeSet)8 Key (org.apache.accumulo.core.data.Key)8 Value (org.apache.accumulo.core.data.Value)8