Пример #1
0
    def delete(self, paths):
        """Delete L{Tag}s matching C{paths}.

        L{TagValue}s and permissions associated with the deleted L{Tag}s are
        removed by cascading deletes in the database schema.

        @param paths: A sequence of L{Tag.path}s.
        @return: A C{list} of C{(objectID, Tag.path)} 2-tuples representing the
            L{Tag}s that were removed.
        """
        if isgenerator(paths):
            paths = list(paths)
        result = getTags(paths=paths)
        deletedTagPaths = list(result.values(Tag.objectID, Tag.path))
        # Delete the fluiddb/tags/description tag values stored for removed
        # tags.  Associated TagValue's are removed by an ON DELETE CASCADE
        # trigger.
        self._factory.tagValues(self._user).delete(
            [(objectID, path) for objectID, _ in deletedTagPaths
             for path in [u'fluiddb/tags/description', u'fluiddb/tags/path']])

        # Touch all the objects for the given tag paths.
        objectIDs = list(getObjectIDs(paths))
        touchObjects(objectIDs)

        result.remove()
        return deletedTagPaths
Пример #2
0
def deleteTagValues(store, tagIDs, objectIDs):
    """Delete those L{TagValue}s whose tagID is in tagIDs and whose
    objectID is in objectIDs.

    @param store: The store to use when fetching data.
    @param tagIDs: A sequence of L{TagValue.tagID}s to match values against.
    @param objectIDs: A sequence of L{TagValue.objectID}s to match values
        against.
    """
    result = store.find(And(TagValue.tagID.is_in(tagIDs),
                            TagValue.objectID.is_in(objectIDs))).remove()
    if result:
        touchObjects(objectIDs)
Пример #3
0
def deleteTagValues(store, tagIDs, objectIDs):
    """Delete those L{TagValue}s whose tagID is in tagIDs and whose
    objectID is in objectIDs.

    @param store: The store to use when fetching data.
    @param tagIDs: A sequence of L{TagValue.tagID}s to match values against.
    @param objectIDs: A sequence of L{TagValue.objectID}s to match values
        against.
    """
    result = store.find(
        And(TagValue.tagID.is_in(tagIDs),
            TagValue.objectID.is_in(objectIDs))).remove()
    if result:
        touchObjects(objectIDs)
Пример #4
0
def batchIndex(objectsFilename, interval, maxObjects, sleepFunction=None):
    """
    Touches all the objects in a given file in batches every a given interval.

    @param objectsFilename: The path of the file with the object IDS to touch.
    @param interval: The interval in minutes to touch a batch of objects.
    @param maxObjects: The number of objects to process in each batch.
    @param sleepFunction: a C{time.sleep} like function used for testing
        purposes.
    """
    if sleepFunction is None:
        sleepFunction = time.sleep
    objectIDs = []
    batch = 0
    interval = interval * 60
    with open(objectsFilename) as objectsFile:
        for line in objectsFile:
            if len(objectIDs) == 0:
                logging.info('Processing batch %d (%d objects processed).' %
                             (batch, batch * maxObjects))
            try:
                objectID = UUID(line.strip())
                objectIDs.append(objectID)
            except ValueError:
                logging.error('Invalid objectID: %r', line)
                continue
            if len(objectIDs) >= maxObjects:
                touchObjects(objectIDs)
                try:
                    transaction.commit()
                except:
                    transaction.abort()
                    raise
                logging.info('Batch done. Sleeping until next batch.')
                objectIDs = []
                batch += 1
                sleepFunction(interval)
        touchObjects(objectIDs)
        try:
            transaction.commit()
        except:
            transaction.abort()
            raise
        logging.info('All objects processed.')
Пример #5
0
def batchIndex(objectsFilename, interval, maxObjects, sleepFunction=None):
    """
    Touches all the objects in a given file in batches every a given interval.

    @param objectsFilename: The path of the file with the object IDS to touch.
    @param interval: The interval in minutes to touch a batch of objects.
    @param maxObjects: The number of objects to process in each batch.
    @param sleepFunction: a C{time.sleep} like function used for testing
        purposes.
    """
    if sleepFunction is None:
        sleepFunction = time.sleep
    objectIDs = []
    batch = 0
    interval = interval * 60
    with open(objectsFilename) as objectsFile:
        for line in objectsFile:
            if len(objectIDs) == 0:
                logging.info('Processing batch %d (%d objects processed).'
                             % (batch, batch * maxObjects))
            try:
                objectID = UUID(line.strip())
                objectIDs.append(objectID)
            except ValueError:
                logging.error('Invalid objectID: %r', line)
                continue
            if len(objectIDs) >= maxObjects:
                touchObjects(objectIDs)
                try:
                    transaction.commit()
                except:
                    transaction.abort()
                    raise
                logging.info('Batch done. Sleeping until next batch.')
                objectIDs = []
                batch += 1
                sleepFunction(interval)
        touchObjects(objectIDs)
        try:
            transaction.commit()
        except:
            transaction.abort()
            raise
        logging.info('All objects processed.')
Пример #6
0
    def delete(self, values):
        """Delete L{TagValue}s.

        @param values: A sequence of C{(objectID, Tag.path)} 2-tuples to
            delete values for.
        @raise FeatureError: Raised if the given list of values is empty.
        @return: The number of values deleted.
        """
        if isgenerator(values):
            values = list(values)
        if not values:
            raise FeatureError("Can't delete an empty list of tag values.")

        paths = set([path for objectID, path in values])
        objectIDs = set([objectID for objectID, path in values])
        tagIDs = dict(getTags(paths).values(Tag.path, Tag.id))
        values = [(objectID, tagIDs[path]) for objectID, path in values]
        result = getTagValues(values).remove()
        if result:
            touchObjects(objectIDs)
        return result
Пример #7
0
    def delete(self, values):
        """Delete L{TagValue}s.

        @param values: A sequence of C{(objectID, Tag.path)} 2-tuples to
            delete values for.
        @raise FeatureError: Raised if the given list of values is empty.
        @return: The number of values deleted.
        """
        if isgenerator(values):
            values = list(values)
        if not values:
            raise FeatureError("Can't delete an empty list of tag values.")

        paths = set([path for objectID, path in values])
        objectIDs = set([objectID for objectID, path in values])
        tagIDs = dict(getTags(paths).values(Tag.path, Tag.id))
        values = [(objectID, tagIDs[path]) for objectID, path in values]
        result = getTagValues(values).remove()
        if result:
            touchObjects(objectIDs)
        return result
Пример #8
0
 def testTouchObjects(self):
     """L{touchObjects} adds the objects to the C{dirty_objects} table."""
     objectID = uuid4()
     touchObjects([objectID])
     self.assertNotIdentical(None, getDirtyObjects([objectID]).one())
Пример #9
0
    def set(self, values):
        """Set or update L{TagValue}s.

        L{Tag}s that don't exist are created automatically before L{TagValue}s
        are stored.  Associated L{TagPermission}s are created automatically
        with the system-wide default permissions.

        @param values: A C{dict} mapping object IDs to tags and values,
            matching the following format::

              {<object-id>: {<path>: <value>,
                             <path>: {'mime-type': <mime-type>,
                                      'contents': <contents>}}}

            A binary L{TagValue} is represented using a different layout than
            other values types, as shown for the second value.
        @raise FeatureError: Raised if the given list of values is empty.
        @raise MalformedPathError: Raised if one of the given paths for a
            nonexistent tag is empty or has unacceptable characters.
        """
        if not values:
            raise FeatureError("Can't set an empty list of tag values.")

        objectIDs = set(values.keys())

        # Implicitly create missing tags, if there are any.
        paths = set()
        for tagValues in values.itervalues():
            paths.update(tagValues.iterkeys())
        tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id))
        existingPaths = set(tagIDs.iterkeys())
        unknownPaths = paths - existingPaths
        if unknownPaths:
            tags = [(path, u'Object for the attribute %s' % path)
                    for path in unknownPaths]
            self._factory.tags(self._user).create(tags)
            tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id))

        # Delete all existing tag values for the specified object IDs and
        # paths.
        deleteValues = []
        for objectID in values:
            for path in values[objectID].iterkeys():
                deleteValues.append((objectID, tagIDs[path]))
        getTagValues(deleteValues).remove()

        # Set new tag values for the specified object IDs and paths.
        for objectID in values:
            tagValues = values[objectID]
            for path, value in tagValues.iteritems():
                tagID = tagIDs[path]

                if isinstance(value, dict):
                    content = value['contents']
                    value = createTagValue(self._user.id, tagID, objectID,
                                           {'mime-type': value['mime-type'],
                                            'size': len(content)})

                    # This is necessary to tell PostgreSQL that generates a
                    # `value.id` immediately.
                    value.id = AutoReload
                    createOpaqueValue(value.id, content)
                else:
                    createTagValue(self._user.id, tagID, objectID, value)
        touchObjects(objectIDs)
Пример #10
0
                result2.remove()
                result.remove()
            # Update the about value.
            value = getAboutTagValues(objectIDs=[tag.objectID]).one()
            if value is not None:
                value.value = newAbout
            else:
                createAboutTagValue(tag.objectID, newAbout)

        print 'Fixing system values'
        tagValues.set(systemValues)

        print 'Touching objects.'
        result = store.find(TagValue.objectID,
                            TagValue.tagID.is_in(currentIDs))
        touchObjects(list(result.config(distinct=True)))
        touchObjects(systemValues.keys())

        i += BATCH_SIZE
        currentIDs = tagsToFix[i:i + BATCH_SIZE]

    print 'Fixing namespaces.'
    i = 0
    currentIDs = namespacesToFix[i:i + BATCH_SIZE]
    while currentIDs:
        systemValues = {}
        for namespace in store.find(Namespace, Namespace.id.is_in(currentIDs)):
            if u'/' in namespace.path:
                root, rest = namespace.path.split('/', 1)
                newPath = u'/'.join([root.lower(), rest])
            else:
Пример #11
0
    def set(self, values):
        """Set or update L{TagValue}s.

        L{Tag}s that don't exist are created automatically before L{TagValue}s
        are stored.  Associated L{TagPermission}s are created automatically
        with the system-wide default permissions.

        @param values: A C{dict} mapping object IDs to tags and values,
            matching the following format::

              {<object-id>: {<path>: <value>,
                             <path>: {'mime-type': <mime-type>,
                                      'contents': <contents>}}}

            A binary L{TagValue} is represented using a different layout than
            other values types, as shown for the second value.
        @raise FeatureError: Raised if the given list of values is empty.
        @raise MalformedPathError: Raised if one of the given paths for a
            nonexistent tag is empty or has unacceptable characters.
        """
        if not values:
            raise FeatureError("Can't set an empty list of tag values.")

        objectIDs = set(values.keys())

        # Implicitly create missing tags, if there are any.
        paths = set()
        for tagValues in values.itervalues():
            paths.update(tagValues.iterkeys())
        tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id))
        existingPaths = set(tagIDs.iterkeys())
        unknownPaths = paths - existingPaths
        if unknownPaths:
            tags = [(path, u'Object for the attribute %s' % path)
                    for path in unknownPaths]
            self._factory.tags(self._user).create(tags)
            tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id))

        # Delete all existing tag values for the specified object IDs and
        # paths.
        deleteValues = []
        for objectID in values:
            for path in values[objectID].iterkeys():
                deleteValues.append((objectID, tagIDs[path]))
        getTagValues(deleteValues).remove()

        # Set new tag values for the specified object IDs and paths.
        for objectID in values:
            tagValues = values[objectID]
            for path, value in tagValues.iteritems():
                tagID = tagIDs[path]

                if isinstance(value, dict):
                    content = value['contents']
                    value = createTagValue(self._user.id, tagID, objectID, {
                        'mime-type': value['mime-type'],
                        'size': len(content)
                    })

                    # This is necessary to tell PostgreSQL that generates a
                    # `value.id` immediately.
                    value.id = AutoReload
                    createOpaqueValue(value.id, content)
                else:
                    createTagValue(self._user.id, tagID, objectID, value)
        touchObjects(objectIDs)
Пример #12
0
 def testTouchObjects(self):
     """L{touchObjects} adds the objects to the C{dirty_objects} table."""
     objectID = uuid4()
     touchObjects([objectID])
     self.assertNotIdentical(None, getDirtyObjects([objectID]).one())