Exemple #1
0
class StatBucket(item.Item):
    """
    Obsolete.  Only present for schema compatibility.  Do not use.
    """
    schemaVersion = 2
    type = attributes.text(doc="A stat name, such as 'messagesReceived'")
    value = attributes.ieee754_double(default=0.0, doc='Total number of events for this time period')
    interval = attributes.text(doc='A time period, e.g. "quarter-hour" or "minute" or "day"')
    index = attributes.integer(doc='The position in the round-robin list for non-daily stats')
    time = attributes.timestamp(doc='When this bucket was last updated')
    attributes.compoundIndex(interval, type, index)
    attributes.compoundIndex(index, interval)
class Header(item.Item):
    """
    Database resident representation of a MIME header.
    """
    typeName = 'quotient_mime_header'
    schemaVersion = 1

    message = attributes.reference(
        "A reference to the stored top-level L{xquotient.exmess.Message} "
        "object to which this header pertains.",
        reftype=exmess.Message,
        whenDeleted=attributes.reference.CASCADE)
    part = attributes.reference(
        "A reference to the stored MIME part object to which this header "
        "directly pertains.")

    name = attributes.text("The name of this header.  What it is called.",
                           allowNone=False)
    value = attributes.text("The decoded value of this header.",
                            allowNone=False)
    index = attributes.integer("The position of this header within a part.",
                               indexed=True,
                               allowNone=False)

    # This compound index matches the getHeader[s] query and is critical for
    # interactive performance.

    attributes.compoundIndex(part, name)
Exemple #3
0
class TestItem(item.Item):
    schemaVersion = 1
    typeName = 'TestItem'
    foo = attributes.integer(indexed=True, default=10)
    bar = attributes.text()
    baz = attributes.timestamp()
    other = attributes.reference()
    booleanT = attributes.boolean()
    booleanF = attributes.boolean()

    activated = attributes.inmemory()
    checkactive = attributes.inmemory()
    checked = attributes.inmemory()

    myStore = attributes.reference()

    attributes.compoundIndex(bar, baz)

    def activate(self):
        self.activated = True
        if getattr(self, 'checkactive', False):
            assert isinstance(self.other, TestItem), repr(self.other)
            assert self.other != self, repr(self.other)
            self.checked = True
class MultiColumnSortHelper(Item):
    columnOne = integer()
    columnTwo = integer()
    compoundIndex(columnOne, columnTwo)
class SingleColumnSortHelper(Item):
    mainColumn = integer(indexed=True)
    other = integer()
    compoundIndex(mainColumn, other)
Exemple #6
0
class SearchEntry(Item):
    """
    An entry in the search index.

    Each combination of the attributes on this item forms a unique entry in the
    index. The primary querying operation supported is matching on the
    C{(searchClass, environment, indexType, searchValue)} portion, with exact
    or prefix matching on the I{searchValue} component depending on the
    I{searchClass} component.

    "Separate" indexes are keyed by C{(searchClass, environment, indexType)}.
    I{environment} and I{indexType} are separated as a convenience to clients
    as separating them allows for easily differentiating between application
    environments at a global configuration level, as well as between different
    indexes within the application.
    """
    searchClass = text(doc="""
    The search "class" that this entry belongs to; must be a value from
    L{SearchClasses}.
    """,
                       allowNone=False)

    environment = text(doc="""
    The environment in which this entry exists.

    Usually something like C{u'prod'}.
    """,
                       allowNone=False)

    indexType = text(doc="""
    The index type for this index entry.

    Usually something like C{u'idNumber'}.
    """,
                     allowNone=False)

    searchValue = text(doc="""
    The search value that this entry should match.
    """,
                       allowNone=False)

    searchType = text(doc="""
    The search type that this entry should match.
    """,
                      allowNone=False)

    result = text(doc="""
    The search result that should be returned when this entry matches.
    """,
                  allowNone=False)

    compoundIndex(searchClass, environment, indexType, searchValue, searchType,
                  result)
    compoundIndex(searchClass, environment, indexType, result, searchType)

    _searchNoise = compile(u'[^\w,]', UNICODE)

    @classmethod
    def _normalize(cls, value):
        """
        Normalize a search value.

        @type value: L{unicode}
        @param value: The value to normalize.

        @rtype: L{unicode}
        @return: The normalized value.
        """
        return cls._searchNoise.sub(u'', casefold(normalize('NFC', value)))

    @classmethod
    def search(cls,
               store,
               searchClass,
               environment,
               indexType,
               searchValue,
               searchType=None,
               limit=200):
        """
        Return entries matching the given search.

        @see: L{SearchEntry}
        """
        with METRIC_SEARCH_QUERY_LATENCY.labels(searchClass.value, environment,
                                                indexType).time():
            criteria = []
            searchValue = cls._normalize(searchValue)
            if searchClass == SearchClasses.EXACT:
                criteria.append(SearchEntry.searchValue == searchValue)
            elif searchClass == SearchClasses.PREFIX:
                criteria.append(
                    SearchEntry.searchValue.startswith(searchValue))
            else:
                raise RuntimeError(
                    'Invalid search class: {!r}'.format(searchClass))
            if searchValue == u'':
                METRIC_SEARCH_REJECTED.labels(searchClass.value, environment,
                                              indexType).inc()
                return []
            criteria.extend([
                SearchEntry.searchClass == searchClass.value,
                SearchEntry.environment == environment,
                SearchEntry.indexType == indexType,
            ])
            if searchType is not None:
                criteria.append(SearchEntry.searchType == searchType)
            query = store.query(SearchEntry, AND(*criteria), limit=limit)
            return [{
                u'result': item.result,
                u'type': item.searchType
            } for item in query]

    @classmethod
    def insert(cls, store, searchClass, environment, indexType, result,
               searchType, searchValue):
        """
        Insert an entry into the search index.

        @see: L{SearchEntry}
        """
        with METRIC_SEARCH_INSERT_LATENCY.labels(searchClass.value,
                                                 environment,
                                                 indexType).time():
            searchValue = cls._normalize(searchValue)
            entry = store.findUnique(
                SearchEntry,
                AND(SearchEntry.searchClass == searchClass.value,
                    SearchEntry.environment == environment,
                    SearchEntry.indexType == indexType,
                    SearchEntry.result == result,
                    SearchEntry.searchType == searchType), None)
            if entry is None:
                if searchValue != u'':
                    SearchEntry(store=store,
                                searchClass=searchClass.value,
                                environment=environment,
                                indexType=indexType,
                                result=result,
                                searchType=searchType,
                                searchValue=searchValue)
            else:
                if searchValue == u'':
                    entry.deleteFromStore()
                else:
                    entry.searchValue = searchValue

    @classmethod
    def remove(cls, store, searchClass, environment, indexType, result,
               searchType):
        """
        Remove an entry from the search index.

        @see: L{SearchEntry}
        """
        with METRIC_SEARCH_DELETE_LATENCY.labels(searchClass.value,
                                                 environment,
                                                 indexType).time():
            store.query(
                SearchEntry,
                AND(SearchEntry.searchClass == searchClass.value,
                    SearchEntry.environment == environment,
                    SearchEntry.indexType == indexType,
                    SearchEntry.result == result,
                    SearchEntry.searchType == searchType)).deleteFromStore()
Exemple #7
0
class LookupEntry(Item):
    """
    An entry in the lookup index.

    Each combination of C{(environment, indexType, key)} identifies a unique
    item in the index.
    """
    environment = text(doc="""
    The environment in which this entry exists.

    Usually something like C{u'prod'}.
    """, allowNone=False)

    indexType = text(doc="""
    The index type for this index entry.

    Usually something like C{u'idNumber'}.
    """, allowNone=False)

    key = text(doc="""
    The key for this index entry.
    """, allowNone=False)

    value = bytes(doc="""
    The value for this index entry.
    """, allowNone=False, default=b'')

    compoundIndex(environment, indexType, key)

    @classmethod
    def get(cls, store, environment, indexType, key):
        """
        Get the value of an index entry.

        @type store: L{axiom.store.Store}
        @param store: The store to use.

        @type environment: L{unicode}
        @param environment: The environment.

        @type indexType: L{unicode}
        @param indexType: The type.

        @type key: L{unicode}
        @param key: The key.

        @raises KeyError: if the entry does not exist.
        """
        with METRIC_LOOKUP_QUERY_LATENCY.labels(environment, indexType).time():
            return store.findUnique(
                cls,
                AND(cls.environment == environment,
                    cls.indexType == indexType,
                    cls.key == key)).value


    @classmethod
    def set(cls, store, environment, indexType, key, value):
        """
        Set the value of an index entry.

        If the entry already exists in the index, the previous value will be
        overwritten.

        @type store: L{axiom.store.Store}
        @param store: The store to use.

        @type environment: L{unicode}
        @param environment: The environment.

        @type indexType: L{unicode}
        @param indexType: The type.

        @type key: L{unicode}
        @param key: The key.

        @type value: L{bytes}
        @param value: The value to set.
        """
        with METRIC_LOOKUP_INSERT_LATENCY.labels(environment, indexType).time():
            item = store.findOrCreate(
                cls,
                environment=environment,
                indexType=indexType,
                key=key)
            item.value = value