def test_memory_growth_transactions_changing_values(self):
        connectionState = DatabaseConnectionState()

        m0 = currentMemUsageMb()

        for i in range(20000):
            connectionState.incomingTransaction(
                i,
                {ObjectFieldId(objId=0, fieldId=0, isIndexValue=False): b" " * i},
                {IndexId(fieldId=0, indexValue=b" " * i): (0,)},
                {IndexId(fieldId=0, indexValue=b" " * (i-1)): (0,)} if i > 0 else {},
            )

        self.assertLess(currentMemUsageMb() - m0, 1)
Ejemplo n.º 2
0
    def _parseSubscriptionMsg(self, channel, msg):
        schema_name = msg.schema

        definition = channel.definedSchemas.get(schema_name)

        assert definition is not None, "can't subscribe to a schema we don't know about!"

        assert msg.typename is not None
        typename = msg.typename

        assert typename in definition, (
            "Can't subscribe to a type we didn't define in the schema: %s not in %s"
            % (typename, list(definition)))

        typedef = definition[typename]

        if msg.fieldname_and_value is None:
            field, val = " exists", indexValueFor(bool, True)
        else:
            field, val = msg.fieldname_and_value

        if field == '_identity':
            # single value identities are encoded as integers
            identities = set([deserialize(ObjectBase, val)._identity])
        else:
            fieldId = self._currentTypeMap().lookupOrAdd(
                schema_name, typename, field)

            identities = set(
                self._kvstore.getSetMembers(
                    IndexId(fieldId=fieldId, indexValue=val)))

        return typedef, identities
Ejemplo n.º 3
0
    def _indexValuesToSetAdds(self, indexValues):
        # indexValues contains (schema:typename:identity:fieldname -> indexHashVal) which builds
        # up the indices we need. We need to transpose to a dictionary ordered by the hash values,
        # not the identities

        t0 = time.time()
        heartbeatInterval = getHeartbeatInterval()

        setAdds = {}

        for iv in indexValues:
            val = indexValues[iv]

            if val is not None:
                fieldId = iv.fieldId
                identity = iv.objId

                index_key = IndexId(fieldId=fieldId, indexValue=val)

                setAdds.setdefault(index_key, set()).add(identity)

                # this could take a long time, so we need to keep heartbeating
                if time.time() - t0 > heartbeatInterval:
                    # note that this needs to be 'sendMessage' which sends immediately,
                    # not, 'write' which queues the message after this function finishes!
                    self._channel.sendMessage(
                        ClientToServer.Heartbeat()
                    )
                    t0 = time.time()
        return setAdds
Ejemplo n.º 4
0
    def _dropConnectionEntry(self, entry):
        identity = entry._identity

        fieldId = self._currentTypeMap().fieldIdFor("core", "Connection",
                                                    " exists")

        exists_key = ObjectFieldId(objId=identity, fieldId=fieldId)
        exists_index = IndexId(fieldId=fieldId,
                               indexValue=indexValueFor(bool, True))

        self._handleNewTransaction(None, {exists_key: None}, {},
                                   {exists_index: set([identity])}, [], [],
                                   self._cur_transaction_num)
Ejemplo n.º 5
0
    def _removeOldDeadConnections(self):
        fieldId = self._currentTypeMap().fieldIdFor("core", "Connection",
                                                    " exists")
        exists_index = IndexId(fieldId=fieldId,
                               indexValue=indexValueFor(bool, True))

        oldIds = self._kvstore.getSetMembers(exists_index)

        if oldIds:
            self._kvstore.setSeveral(
                {
                    ObjectFieldId(objId=identity, fieldId=fieldId): None
                    for identity in oldIds
                }, {}, {exists_index: set(oldIds)})
Ejemplo n.º 6
0
    def _createConnectionEntry(self):
        identity = self.identityProducer.createIdentity()
        fieldId = self._currentTypeMap().fieldIdFor("core", "Connection",
                                                    " exists")

        exists_key = ObjectFieldId(objId=identity, fieldId=fieldId)
        exists_index = IndexId(fieldId=fieldId,
                               indexValue=indexValueFor(bool, True))
        identityRoot = self.allocateNewIdentityRoot()

        self._handleNewTransaction(None, {exists_key: serialize(bool, True)},
                                   {exists_index: set([identity])}, {}, [], [],
                                   self._cur_transaction_num)

        return core_schema.Connection.fromIdentity(identity), identityRoot
Ejemplo n.º 7
0
    def _increaseBroadcastTransactionToInclude(self, channel, indexKey, newIds,
                                               key_value, set_adds,
                                               set_removes):
        # we need to include all the data for the objects in 'newIds' to the transaction
        # that we're broadcasting
        fieldId = indexKey.fieldId
        fieldDef = self._currentTypeMap().fieldIdToDef[fieldId]

        typedef = channel.definedSchemas.get(
            fieldDef.schema)[fieldDef.typename]

        key_value.update(
            self._loadValuesForObject(channel, fieldDef.schema,
                                      fieldDef.typename, newIds))

        reverseKeys = []
        for index_name in typedef.indices:
            for ident in newIds:
                reverseKeys.append(
                    ObjectFieldId(fieldId=fieldId,
                                  objId=ident,
                                  isIndexValue=True))

        reverseVals = self._kvstore.getSeveral(reverseKeys)
        reverseKVMap = {
            reverseKeys[i]: reverseVals[i]
            for i in range(len(reverseKeys))
        }

        for index_name in typedef.indices:
            fieldId = self._currentTypeMap().fieldIdFor(
                fieldDef.schema, fieldDef.typename, index_name)

            for ident in newIds:
                fieldval = reverseKVMap.get(
                    ObjectFieldId(fieldId=fieldId, objId=ident))

                if fieldval is not None:
                    ik = IndexId(fieldId=fieldId, indexValue=fieldval)
                    set_adds.setdefault(ik, set()).add(ident)
Ejemplo n.º 8
0
    def _markSubscriptionComplete(self, schema, typename, fieldname_and_value,
                                  identities, connectedChannel, isLazy):
        if fieldname_and_value is not None:
            # this is an index subscription
            for ident in identities:
                self._id_to_channel.setdefault(ident,
                                               set()).add(connectedChannel)

                connectedChannel.subscribedIds.add(ident)

            if fieldname_and_value[0] != '_identity':
                fieldId = self._currentTypeMap().fieldIdFor(
                    schema, typename, fieldname_and_value[0])
                index_key = IndexId(fieldId=fieldId,
                                    indexValue=fieldname_and_value[1])

                if index_key not in self._index_to_channel:
                    self._index_to_channel[index_key] = set()

                self._index_to_channel[index_key].add(connectedChannel)

                connectedChannel.subscribedIndexKeys[
                    index_key] = -1 if not isLazy else self._cur_transaction_num
            else:
                # an object's identity cannot change, so we don't need to track our subscription to it
                assert not isLazy
        else:
            # this is a type-subscription
            for fieldname in connectedChannel.definedSchemas[schema][
                    typename].fields:
                fieldId = self._currentTypeMap().fieldIdFor(
                    schema, typename, fieldname)
                if fieldId not in self._field_id_to_channel:
                    self._field_id_to_channel[fieldId] = set()

                self._field_id_to_channel[fieldId].add(connectedChannel)

                connectedChannel.subscribedFields[
                    fieldId] = -1 if not isLazy else self._cur_transaction_num