Rebuild a tree from MIB objects found at currently loaded modules.

        If currently existing tree is out of date, walk over all Managed Objects
        and Instances to structure Management Instrumentation objects into a tree
        of the following layout:

        MibTree
          |
          +----MibScalar
          |        |
          |        +-----MibScalarInstance
          |
          +----MibTable
          |
          +----MibTableRow
                   |
                   +-------MibTableColumn
                                 |
                                 +------MibScalarInstance(s)

        Notes
        -----
        Only Managed Objects (i.e. `OBJECT-TYPE`) get indexed here, various MIB
        definitions and constants can't be SNMP managed so we drop them.

def _indexMib(self):
        """Rebuild a tree from MIB objects found at currently loaded modules.

        If currently existing tree is out of date, walk over all Managed Objects
        and Instances to structure Management Instrumentation objects into a tree
        of the following layout:

        MibTree
          |
          +----MibScalar
          |        |
          |        +-----MibScalarInstance
          |
          +----MibTable
          |
          +----MibTableRow
                   |
                   +-------MibTableColumn
                                 |
                                 +------MibScalarInstance(s)

        Notes
        -----
        Only Managed Objects (i.e. `OBJECT-TYPE`) get indexed here, various MIB
        definitions and constants can't be SNMP managed so we drop them.
        """
        if self.lastBuildId == self.mibBuilder.lastBuildId:
            return

        (MibScalarInstance, MibScalar,
         MibTableColumn, MibTableRow,
         MibTable) = self.mibBuilder.importSymbols(
            'SNMPv2-SMI', 'MibScalarInstance', 'MibScalar',
            'MibTableColumn', 'MibTableRow', 'MibTable'
        )

        mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso')

        scalars = {}
        instances = {}
        tables = {}
        rows = {}
        cols = {}

        # Sort by module name to give user a chance to slip-in
        # custom MIB modules (that would be sorted out first)
        mibSymbols = list(self.mibBuilder.mibSymbols.items())
        mibSymbols.sort(key=lambda x: x[0], reverse=True)

        for modName, mibMod in mibSymbols:

            for symObj in mibMod.values():

                if isinstance(symObj, MibTable):
                    tables[symObj.name] = symObj

                elif isinstance(symObj, MibTableRow):
                    rows[symObj.name] = symObj

                elif isinstance(symObj, MibTableColumn):
                    cols[symObj.name] = symObj

                elif isinstance(symObj, MibScalarInstance):
                    instances[symObj.name] = symObj

                elif isinstance(symObj, MibScalar):
                    scalars[symObj.name] = symObj

        # Detach items from each other
        for symName, parentName in self.lastBuildSyms.items():

            if parentName in scalars:
                scalars[parentName].unregisterSubtrees(symName)

            elif parentName in cols:
                cols[parentName].unregisterSubtrees(symName)

            elif parentName in rows:
                rows[parentName].unregisterSubtrees(symName)

            else:
                mibTree.unregisterSubtrees(symName)

        lastBuildSyms = {}

        # Attach Managed Objects Instances to Managed Objects
        for inst in instances.values():
            if inst.typeName in scalars:
                scalars[inst.typeName].registerSubtrees(inst)

            elif inst.typeName in cols:
                cols[inst.typeName].registerSubtrees(inst)

            else:
                raise error.SmiError(
                    'Orphan MIB scalar instance %r at '
                    '%r' % (inst, self))

            lastBuildSyms[inst.name] = inst.typeName

        # Attach Table Columns to Table Rows
        for col in cols.values():
            rowName = col.name[:-1]  # XXX

            if rowName in rows:
                rows[rowName].registerSubtrees(col)

            else:
                raise error.SmiError(
                    'Orphan MIB table column %r at '
                    '%r' % (col, self))

            lastBuildSyms[col.name] = rowName

        # Attach Table Rows to MIB tree
        for row in rows.values():
            mibTree.registerSubtrees(row)
            lastBuildSyms[row.name] = mibTree.name

        # Attach Tables to MIB tree
        for table in tables.values():
            mibTree.registerSubtrees(table)
            lastBuildSyms[table.name] = mibTree.name

        # Attach Scalars to MIB tree
        for scalar in scalars.values():
            mibTree.registerSubtrees(scalar)
            lastBuildSyms[scalar.name] = mibTree.name

        self.lastBuildSyms = lastBuildSyms

        self.lastBuildId = self.mibBuilder.lastBuildId

        debug.logger & debug.FLAG_INS and debug.logger('_indexMib: rebuilt')