Example #1
0
    def cron_manager(self):
        database = self.database

        # Build fake context
        context = get_fake_context(database, self.root.context_cls)
        context.server = self
        context.init_context()
        context.is_cron = True

        # Go
        query = RangeQuery('next_time_event', None, context.timestamp)
        for brain in database.search(query).get_documents():
            payload = pickle.loads(brain.next_time_event_payload)
            resource = database.get_resource(brain.abspath)
            try:
                resource.time_event(payload)
            except Exception:
                # Log error
                log_error('Cron error\n' + format_exc())
                context.root.alert_on_internal_server_error(context)
            # Reindex resource without committing
            catalog = database.catalog
            catalog.unindex_document(str(resource.abspath))
            catalog.index_document(resource.get_catalog_values())
            catalog.save_changes()

        # Save changes
        database.save_changes()

        # Again, and again
        return self.config.get_value('cron-interval')
Example #2
0
    def cron_manager(self):
        database = self.database

        # Build fake context
        context = get_fake_context(database)
        context.server = self
        context.init_context()

        # Go
        query = RangeQuery('next_time_event', None, context.timestamp)
        for brain in database.search(query).get_documents():
            payload = pickle.loads(brain.next_time_event_payload)
            resource = database.get_resource(brain.abspath)
            resource.time_event(payload)
            # Reindex resource without committing
            catalog = database.catalog
            catalog.unindex_document(str(resource.abspath))
            catalog.index_document(resource.get_catalog_values())
            catalog.save_changes()

        # Save changes
        database.save_changes()

        # Again, and again
        return self.config.get_value('cron-interval')
Example #3
0
 def test_everything(self):
     database = self.database
     # Simple Search, hit
     results = database.search(data=u'lion')
     self.assertEqual(len(results), 5)
     documents = [
         x.abspath for x in results.get_documents(sort_by='abspath')
     ]
     self.assertEqual(documents,
                      ['03.txt', '08.txt', '10.txt', '23.txt', '99.txt.fr'])
     # Simple Search, miss
     self.assertEqual(len(database.search(data=u'tiger')), 0)
     # Unindex, Search, Abort, Search
     database.catalog.unindex_document('03.txt')
     results = database.search(data=u'lion')
     self.assertEqual(len(database.search(data=u'lion')), 4)
     database.catalog.abort_changes()
     self.assertEqual(len(database.search(data=u'lion')), 5)
     # Query on indexed boolean
     self.assertEqual(len(database.search(about_wolf=True)), 5)
     # Query on stored boolean
     results = database.search(about_wolf=True)
     longer_stories = 0
     for result in results.get_documents():
         if result.is_long:
             longer_stories += 1
     self.assertEqual(longer_stories, 0)
     # Phrase Query
     results = database.search(data=u'this is a double death')
     self.assertEqual(len(results), 1)
     # Range Query
     query = RangeQuery('abspath', '03.txt', '06.txt')
     results = database.search(query)
     self.assertEqual(len(results), 4)
     # Not Query (1/2)
     query = NotQuery(PhraseQuery('data', u'lion'))
     results = database.search(query)
     self.assertEqual(len(results), 31)
     # Not Query (2/2)
     query1 = PhraseQuery('data', u'mouse')
     query2 = NotQuery(PhraseQuery('data', u'lion'))
     query = AndQuery(query1, query2)
     results = database.search(query)
     self.assertEqual(len(results), 2)
Example #4
0
def get_base_path_query(path, min_depth=1, max_depth=None):
    """Builds a query that will return all the objects within the given
    absolute path, like it is returned by 'resource.abspath'.

    The minimum and maximum depth parameters are relative to the given path:

    - If the minimum depth is zero it means include the container
    - If the maximum depth is None it means unlimited.
    """
    # Preprocess input data
    if type(path) is not str:
        path = str(path)

    if max_depth is not None and max_depth < min_depth:
        err = 'maximum depth (%d) smaller than minimum depth (%d)'
        raise ValueError, err % (max_depth, min_depth)

    # Special case: everything
    if path == '/' and min_depth == 0 and max_depth is None:
        return AllQuery()

    # Special case: just the given path
    if min_depth == 0 and max_depth == 0:
        return PhraseQuery('abspath', path)

    # Standard case
    query = PhraseQuery('parent_paths', path)
    if min_depth > 1 or max_depth is not None:
        path_depth = path.rstrip('/').count('/')
        a = path_depth + min_depth
        b = path_depth + max_depth if max_depth is not None else None
        query = AndQuery(query, RangeQuery('abspath_depth', a, b))

    if min_depth == 0:
        return OrQuery(query, PhraseQuery('abspath', path))

    return query
Example #5
0
def find_versions_to_update(context, force=False):
    database = context.database
    cls_errors = []
    cls_to_update = []
    # Find classes
    for cls in database.get_resource_classes():
        # Class version
        class_version = class_version_to_date(cls.class_version)
        class_version_tomorrow = class_version + timedelta(days=1)
        # Search for code older than the instance
        query = AndQuery(
            PhraseQuery('format', cls.class_id),
            RangeQuery('class_version', class_version_tomorrow, None))
        search = database.search(query)
        if search:
            resource = search.get_resources().next()
            kw = {
                'class_id': resource.class_id,
                'class_title': resource.class_title,
                'abspath': str(resource.abspath),
                'resource_version': resource.metadata.version,
                'cls_version': resource.class_version
            }
            cls_errors.append(kw)
            if force is False:
                break
        # Find out the versions to upgrade
        classes_and_versions = []
        for sub_cls in cls.mro():
            for name in sub_cls.__dict__.keys():
                if not name.startswith('update_'):
                    continue
                kk, version = name.split('_', 1)
                if len(version) != 8:
                    continue
                if not version.isdigit():
                    continue
                class_version = class_version_to_date(version)
                if class_version > class_version_to_date(cls.class_version):
                    raise ValueError('{0} class_version is bad'.format(
                        sub_cls.class_id))
                class_version_yesterday = class_version - timedelta(days=1)
                query = AndQuery(
                    PhraseQuery('format', cls.class_id),
                    RangeQuery('class_version', None, class_version_yesterday))
                search = database.search(query)
                if not search:
                    continue
                class_and_version = (cls.class_id, version)
                if class_and_version in classes_and_versions:
                    # Overriden update method in sub classes
                    # So update method should be done one time
                    continue
                classes_and_versions.append(class_and_version)
                update_title_name = 'update_{0}_title'.format(version)
                update_title = getattr(cls, update_title_name, MSG(u'Unknow'))
                kw = {
                    'class_id': cls.class_id,
                    'class_title': cls.class_title,
                    'class_version': version,
                    'class_version_date': class_version,
                    'class_version_pretty': context.format_date(class_version),
                    'update_title': update_title.gettext(),
                    'nb_resources': len(search)
                }
                cls_to_update.append(kw)
    # Sort
    cls_to_update.sort(key=itemgetter('class_version_date'))
    # Ok
    return {'cls_to_update': cls_to_update, 'cls_errors': cls_errors}
Example #6
0
def run_next_update_method(context, force=False):
    """Update the database to the given versions.
    """
    database = context.database
    log = open('%s/log/update' % database.path, 'w')
    messages = []

    versions = find_versions_to_update(context, force)
    if not versions['cls_to_update']:
        return
    # Update
    version = versions['cls_to_update'][0]
    class_version = version['class_version_date']
    class_version_yesterday = class_version - timedelta(days=1)
    query = AndQuery(
        PhraseQuery('format', version['class_id']),
        RangeQuery('class_version', None, class_version_yesterday))
    search = context.database.search(query)
    # Update
    resources_old2new = database.resources_old2new
    for resource in search.get_resources():
        path = str(resource.abspath)
        abspath = resources_old2new.get(path, path)
        if abspath is None:
            # resource deleted
            continue
        # Reindex on errors
        obj_version = resource.metadata.version
        cls_version = resource.class_version
        next_versions = resource.get_next_versions()
        if (obj_version == cls_version or not next_versions
                or next_versions[0] != version['class_version']):
            database.catalog.unindex_document(str(resource.abspath))
            values = resource.get_catalog_values()
            database.catalog.index_document(values)
            continue

        try:
            if resource is not None:
                # If resource has not been removed
                resource.update(version['class_version'])
        except Exception:
            line = 'ERROR: "{0}" - class_id: "{1}"\n'.format(
                resource.abspath, resource.__class__.class_id)
            log.write(line)
            print_exc(file=log)
            log.write('\n')
            # Add message
            messages.append(line)
            if force is False:
                return messages
    # Commit
    if not database.has_changed:
        # We reindex so the class_version is reindexed
        database.catalog.save_changes()
    else:
        # Commit (Do not override the mtime/author)
        git_message = u'Upgrade to version {0}'.format(
            version['class_version'])
        context.git_message = git_message
        context.set_mtime = False
        database.save_changes()
    # Ok
    return messages