--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -1,7 +1,9 @@
import sys
import time
+from collections import defaultdict
import tg
+import pymongo
from pylons import c
from paste.deploy.converters import asint
@@ -62,30 +64,69 @@
def command(self):
from allura import model as M
self.basic_setup()
- projects = M.Project.query.find().all()
- base.log.info('Building global indexes')
+ # Collect indexes by collection name
+ main_indexes = defaultdict(lambda: ([], []))
+ project_indexes = defaultdict(lambda: ([], []))
+ base.log.info('Collecting indexes...')
for name, cls in MappedClass._registry.iteritems():
+ cname = cls.__mongometa__.name
+ if cname is None:
+ base.log.info('... skipping abstract class %s', cls)
+ continue
+ base.log.info('... for class %s', cls)
+ indexes = getattr(cls.__mongometa__, 'indexes', []) or []
+ uindexes = getattr(cls.__mongometa__, 'unique_indexes', []) or []
if cls.__mongometa__.session in (
M.main_orm_session, M.repository_orm_session):
- base.log.info('... for class %s', cls)
- M.main_orm_session.update_indexes(cls, background=True)
+ idx = main_indexes[cname]
else:
- continue
+ idx = project_indexes[cname]
+ idx[0].extend(indexes)
+ idx[1].extend(uindexes)
+ base.log.info('Updating indexes for main DB')
+ db = M.main_doc_session.db
+ for name, (indexes, uindexes) in main_indexes.iteritems():
+ self._update_indexes(db[name], indexes, uindexes)
+ base.log.info('Updating indexes for project DBs')
+ projects = M.Project.query.find().all()
configured_dbs = set()
for p in projects:
- db = p.database or p.database_uri
+ db = p.database_uri
if db in configured_dbs: continue
configured_dbs.add(db)
- if not p.database_configured: continue
- time.sleep(asint(tg.config.get('ensure_index.sleep', 2)))
- base.log.info('Building project indexes for %s', p.shortname)
- for name, cls in MappedClass._registry.iteritems():
- if cls.__mongometa__.session == M.main_orm_session:
- continue
- base.log.info('... for class %s', cls)
- c.project = p
- if session(cls) is None: continue
- session(cls).update_indexes(cls, background=True)
+ c.project = p
+ db = M.project_doc_session.db
+ base.log.info('... DB: %s', db)
+ for name, (indexes, uindexes) in project_indexes.iteritems():
+ self._update_indexes(db[name], indexes, uindexes)
+
+ def _update_indexes(self, collection, indexes, uindexes):
+ indexes = set(map(tuple, indexes))
+ uindexes = set(map(tuple, uindexes))
+ prev_indexes = {}
+ prev_uindexes = {}
+ for iname, fields in collection.index_information().iteritems():
+ if iname == '_id_': continue
+ if fields.get('unique'):
+ prev_uindexes[iname] = tuple(fields['key'])
+ else:
+ prev_indexes[iname] = tuple(fields['key'])
+ # Drop obsolete indexes
+ for iname, key in prev_indexes.iteritems():
+ if key not in indexes:
+ base.log.info('...... drop index %s:%s', collection.name, iname)
+ collection.drop_index(iname)
+ for iname, key in prev_uindexes.iteritems():
+ if key not in uindexes:
+ base.log.info('...... drop index %s:%s', collection.name, iname)
+ collection.drop_index(iname)
+ # Ensure all indexes
+ for idx in map(list, indexes):
+ base.log.info('...... ensure index %s:%s', collection.name, idx)
+ collection.ensure_index(idx, background=True)
+ for idx in map(list, uindexes):
+ base.log.info('...... ensure unique index %s:%s', collection.name, idx)
+ collection.ensure_index(idx, background=True, unique=True)
def build_model_inheritance_graph():
graph = dict((c, ([], [])) for c in MappedClass._registry.itervalues())