This file is indexed.

/usr/lib/python2.7/dist-packages/ovs/db/custom_index.py is in python-openvswitch 2.9.2-0ubuntu0.18.04.3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import collections
import functools
import operator
try:
    from UserDict import IterableUserDict as DictBase
except ImportError:
    from collections import UserDict as DictBase

try:
    import sortedcontainers
except ImportError:
    from ovs.compat import sortedcontainers

from ovs.db import data

OVSDB_INDEX_ASC = "ASC"
OVSDB_INDEX_DESC = "DESC"
ColumnIndex = collections.namedtuple('ColumnIndex',
                                     ['column', 'direction', 'key'])


class MultiColumnIndex(object):
    def __init__(self, name):
        self.name = name
        self.columns = []
        self.clear()

    def __repr__(self):
        return "{}(name={})".format(self.__class__.__name__, self.name)

    def __str__(self):
        return repr(self) + " columns={} values={}".format(
            self.columns, [str(v) for v in self.values])

    def add_column(self, column, direction=OVSDB_INDEX_ASC, key=None):
        self.columns.append(ColumnIndex(column, direction,
                             key or operator.attrgetter(column)))

    def add_columns(self, *columns):
        self.columns.extend(ColumnIndex(col, OVSDB_INDEX_ASC,
                                        operator.attrgetter(col))
                            for col in columns)

    def _cmp(self, a, b):
        for col, direction, key in self.columns:
            aval, bval = key(a), key(b)
            if aval == bval:
                continue
            result = (aval > bval) - (aval < bval)
            return result if direction == OVSDB_INDEX_ASC else -result
        return 0

    def index_entry_from_row(self, row):
        return row._table.rows.IndexEntry(
            uuid=row.uuid,
            **{c.column: getattr(row, c.column) for c in self.columns})

    def add(self, row):
        if not all(hasattr(row, col.column) for col in self.columns):
            # This is a new row, but it hasn't had the necessary columns set
            # We'll add it later
            return
        self.values.add(self.index_entry_from_row(row))

    def remove(self, row):
        self.values.remove(self.index_entry_from_row(row))

    def clear(self):
        self.values = sortedcontainers.SortedListWithKey(
            key=functools.cmp_to_key(self._cmp))

    def irange(self, start, end):
        return iter(r._table.rows[r.uuid]
                    for r in self.values.irange(start, end))

    def __iter__(self):
        return iter(r._table.rows[r.uuid] for r in self.values)


class IndexedRows(DictBase, object):
    def __init__(self, table, *args, **kwargs):
        super(IndexedRows, self).__init__(*args, **kwargs)
        self.table = table
        self.indexes = {}
        self.IndexEntry = IndexEntryClass(table)

    def index_create(self, name):
        if name in self.indexes:
            raise ValueError("An index named {} already exists".format(name))
        index = self.indexes[name] = MultiColumnIndex(name)
        return index

    def __setitem__(self, key, item):
        self.data[key] = item
        for index in self.indexes.values():
            index.add(item)

    def __delitem__(self, key):
        val = self.data[key]
        del self.data[key]
        for index in self.indexes.values():
            index.remove(val)

    def clear(self):
        self.data.clear()
        for index in self.indexes.values():
            index.clear()

    # Nothing uses the methods below, though they'd be easy to implement
    def update(self, dict=None, **kwargs):
        raise NotImplementedError()

    def setdefault(self, key, failobj=None):
        raise NotImplementedError()

    def pop(self, key, *args):
        raise NotImplementedError()

    def popitem(self):
        raise NotImplementedError()

    @classmethod
    def fromkeys(cls, iterable, value=None):
        raise NotImplementedError()


def IndexEntryClass(table):
    """Create a class used represent Rows in indexes

    ovs.db.idl.Row, being inherently tied to transaction processing and being
    initialized with dicts of Datums, is not really useable as an object to
    pass to and store in indexes. This method will create a class named after
    the table's name that is initialized with that Table Row's default values.
    For example:

    Port = IndexEntryClass(idl.tables['Port'])

    will create a Port class. This class can then be used to search custom
    indexes. For example:

    for port in idx.iranage(Port(name="test1"), Port(name="test9")):
       ...
    """

    def defaults_uuid_to_row(atom, base):
        return atom.value

    columns = ['uuid'] + list(table.columns.keys())
    cls = collections.namedtuple(table.name, columns)
    cls._table = table
    cls.__new__.__defaults__ = (None,) + tuple(
        data.Datum.default(c.type).to_python(defaults_uuid_to_row)
        for c in table.columns.values())
    return cls