@Override
    public ProcResult fetchResult() throws AnalysisException {
        Preconditions.checkNotNull(globalStateMgr);

        BaseProcResult result = new BaseProcResult();

        result.setNames(TITLE_NAMES);
        List<Long> dbIds = globalStateMgr.getLocalMetastore().getDbIds();
        if (dbIds == null || dbIds.isEmpty()) {
            // empty
            return result;
        }

        SystemInfoService infoService = GlobalStateMgr.getCurrentState().getNodeMgr().getClusterInfo();

        int totalDbNum = 0;
        int totalTableNum = 0;
        int totalPartitionNum = 0;
        int totalIndexNum = 0;
        int totalTabletNum = 0;
        int totalReplicaNum = 0;

        unhealthyTabletIds.clear();
        inconsistentTabletIds.clear();
        errorStateTabletIds.clear();
        cloningTabletIds = AgentTaskQueue.getTabletIdsByType(TTaskType.CLONE);
        List<List<Comparable>> lines = new ArrayList<List<Comparable>>();
        for (Long dbId : dbIds) {
            if (dbId == 0) {
                // skip information_schema database
                continue;
            }
            Database db = globalStateMgr.getDb(dbId);
            if (db == null) {
                continue;
            }

            ++totalDbNum;
            List<Long> aliveBeIdsInCluster = infoService.getBackendIds(true);
            Locker locker = new Locker();
            locker.lockDatabase(db, LockType.READ);
            try {
                int dbTableNum = 0;
                int dbPartitionNum = 0;
                int dbIndexNum = 0;
                int dbTabletNum = 0;
                int dbReplicaNum = 0;

                for (Table table : db.getTables()) {
                    if (!table.isNativeTableOrMaterializedView()) {
                        continue;
                    }

                    ++dbTableNum;
                    OlapTable olapTable = (OlapTable) table;

                    for (Partition partition : olapTable.getAllPartitions()) {
                        short replicationNum = olapTable.getPartitionInfo().getReplicationNum(partition.getId());
                        ++dbPartitionNum;
                        for (PhysicalPartition physicalParition : partition.getSubPartitions()) {
                            for (MaterializedIndex materializedIndex : physicalParition
                                    .getMaterializedIndices(IndexExtState.VISIBLE)) {
                                ++dbIndexNum;
                                for (Tablet tablet : materializedIndex.getTablets()) {
                                    ++dbTabletNum;

                                    if (table.isCloudNativeTableOrMaterializedView()) {
                                        continue;
                                    }

                                    LocalTablet localTablet = (LocalTablet) tablet;
                                    dbReplicaNum += localTablet.getImmutableReplicas().size();
                                    if (localTablet.getErrorStateReplicaNum() > 0) {
                                        errorStateTabletIds.put(dbId, tablet.getId());
                                    }

                                    Pair<TabletHealthStatus, Priority> res = TabletChecker.getTabletHealthStatusWithPriority(
                                            localTablet, infoService, physicalParition.getVisibleVersion(),
                                            replicationNum, aliveBeIdsInCluster, olapTable.getLocation());

                                    // here we treat REDUNDANT as HEALTHY, for user-friendly.
                                    if (res.first != TabletHealthStatus.HEALTHY && res.first != TabletHealthStatus.REDUNDANT
                                            && res.first != TabletHealthStatus.COLOCATE_REDUNDANT &&
                                            res.first != TabletHealthStatus.NEED_FURTHER_REPAIR) {
                                        unhealthyTabletIds.put(dbId, tablet.getId());
                                    }

                                    if (!localTablet.isConsistent()) {
                                        inconsistentTabletIds.put(dbId, tablet.getId());
                                    }
                                } // end for tablets
                            } // end for indices
                        }
                    } // end for partitions
                } // end for tables

                List<Comparable> oneLine = new ArrayList<Comparable>(TITLE_NAMES.size());
                oneLine.add(dbId);
                oneLine.add(db.getFullName());
                oneLine.add(dbTableNum);
                oneLine.add(dbPartitionNum);
                oneLine.add(dbIndexNum);
                oneLine.add(dbTabletNum);
                oneLine.add(dbReplicaNum);
                oneLine.add(unhealthyTabletIds.get(dbId).size());
                oneLine.add(inconsistentTabletIds.get(dbId).size());
                oneLine.add(cloningTabletIds.get(dbId).size());
                oneLine.add(errorStateTabletIds.get(dbId).size());

                lines.add(oneLine);

                totalTableNum += dbTableNum;
                totalPartitionNum += dbPartitionNum;
                totalIndexNum += dbIndexNum;
                totalTabletNum += dbTabletNum;
                totalReplicaNum += dbReplicaNum;
            } finally {
                locker.unLockDatabase(db, LockType.READ);
            }
        } // end for dbs

        // sort by dbName
        ListComparator<List<Comparable>> comparator = new ListComparator<List<Comparable>>(1);
        Collections.sort(lines, comparator);

        // add sum line after sort
        List<Comparable> finalLine = new ArrayList<Comparable>(TITLE_NAMES.size());
        finalLine.add("Total");
        finalLine.add(totalDbNum);
        finalLine.add(totalTableNum);
        finalLine.add(totalPartitionNum);
        finalLine.add(totalIndexNum);
        finalLine.add(totalTabletNum);
        finalLine.add(totalReplicaNum);
        finalLine.add(unhealthyTabletIds.size());
        finalLine.add(inconsistentTabletIds.size());
        finalLine.add(cloningTabletIds.size());
        finalLine.add(errorStateTabletIds.size());
        lines.add(finalLine);

        // add result
        for (List<Comparable> line : lines) {
            List<String> row = new ArrayList<String>(line.size());
            for (Comparable comparable : line) {
                row.add(comparable.toString());
            }
            result.addRow(row);
        }

        return result;
    }
@Test
    public void testFetchResult() throws AnalysisException {
        new StatisticProcDir(GlobalStateMgr.getCurrentState()).fetchResult();
    }