server/checkintegrity.py
branchstable
changeset 6127 747e423093fc
parent 6112 913979c79244
child 6132 440df442d705
equal deleted inserted replaced
6126:aca6a2c357fd 6127:747e423093fc
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
    14 # details.
    14 # details.
    15 #
    15 #
    16 # You should have received a copy of the GNU Lesser General Public License along
    16 # You should have received a copy of the GNU Lesser General Public License along
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 """Check integrity of a CubicWeb repository. Hum actually only the system database
    18 """Integrity checking tool for instances:
    19 is checked.
    19 
       
    20 * integrity of a CubicWeb repository. Hum actually only the system database is
       
    21   checked.
       
    22 
       
    23 * consistency of multi-sources instance mapping file
    20 """
    24 """
    21 
    25 
    22 from __future__ import with_statement
    26 from __future__ import with_statement
    23 
    27 
    24 __docformat__ = "restructuredtext en"
    28 __docformat__ = "restructuredtext en"
    26 import sys
    30 import sys
    27 from datetime import datetime
    31 from datetime import datetime
    28 
    32 
    29 from logilab.common.shellutils import ProgressBar
    33 from logilab.common.shellutils import ProgressBar
    30 
    34 
    31 from cubicweb.schema import PURE_VIRTUAL_RTYPES
    35 from cubicweb.schema import META_RTYPES, VIRTUAL_RTYPES, PURE_VIRTUAL_RTYPES
    32 from cubicweb.server.sqlutils import SQL_PREFIX
    36 from cubicweb.server.sqlutils import SQL_PREFIX
    33 from cubicweb.server.session import security_enabled
    37 from cubicweb.server.session import security_enabled
    34 
    38 
    35 def has_eid(session, sqlcursor, eid, eids):
    39 def has_eid(session, sqlcursor, eid, eids):
    36     """return true if the eid is a valid eid"""
    40     """return true if the eid is a valid eid"""
   323     if reindex:
   327     if reindex:
   324         cnx.rollback()
   328         cnx.rollback()
   325         session.set_pool()
   329         session.set_pool()
   326         reindex_entities(repo.schema, session, withpb=withpb)
   330         reindex_entities(repo.schema, session, withpb=withpb)
   327         cnx.commit()
   331         cnx.commit()
       
   332 
       
   333 
       
   334 def warning(msg, *args):
       
   335     if args:
       
   336         msg = msg % args
       
   337     print 'WARNING: %s' % msg
       
   338 
       
   339 def error(msg, *args):
       
   340     if args:
       
   341         msg = msg % args
       
   342     print 'ERROR: %s' % msg
       
   343 
       
   344 def check_mapping(schema, mapping, warning=warning, error=error):
       
   345     # first check stuff found in mapping file exists in the schema
       
   346     for attr in ('support_entities', 'support_relations'):
       
   347         for ertype in mapping[attr].keys():
       
   348             try:
       
   349                 mapping[attr][ertype] = erschema = schema[ertype]
       
   350             except KeyError:
       
   351                 error('reference to unknown type %s in %s', ertype, attr)
       
   352                 del mapping[attr][ertype]
       
   353             else:
       
   354                 if erschema.final or erschema in META_RTYPES:
       
   355                     error('type %s should not be mapped in %s', ertype, attr)
       
   356                     del mapping[attr][ertype]
       
   357     for attr in ('dont_cross_relations', 'cross_relations'):
       
   358         for rtype in list(mapping[attr]):
       
   359             try:
       
   360                 rschema = schema.rschema(rtype)
       
   361             except KeyError:
       
   362                 error('reference to unknown relation type %s in %s', rtype, attr)
       
   363                 mapping[attr].remove(rtype)
       
   364             else:
       
   365                 if rschema.final or rschema in VIRTUAL_RTYPES:
       
   366                     error('relation type %s should not be mapped in %s',
       
   367                           rtype, attr)
       
   368                     mapping[attr].remove(rtype)
       
   369     # check relation in dont_cross_relations aren't in support_relations
       
   370     for rschema in mapping['dont_cross_relations']:
       
   371         if rschema in mapping['support_relations']:
       
   372             warning('relation %s is in dont_cross_relations and in support_relations',
       
   373                     rschema)
       
   374     # check relation in cross_relations are in support_relations
       
   375     for rschema in mapping['cross_relations']:
       
   376         if rschema not in mapping['support_relations']:
       
   377             warning('relation %s is in cross_relations but not in support_relations',
       
   378                     rschema)
       
   379     # check for relation in both cross_relations and dont_cross_relations
       
   380     for rschema in mapping['cross_relations'] & mapping['dont_cross_relations']:
       
   381         error('relation %s is in both cross_relations and dont_cross_relations',
       
   382               rschema)
       
   383     # now check for more handy things
       
   384     seen = set()
       
   385     for eschema in mapping['support_entities'].values():
       
   386         for rschema, ttypes, role in eschema.relation_definitions():
       
   387             if rschema in META_RTYPES:
       
   388                 continue
       
   389             ttypes = [ttype for ttype in ttypes if ttype in mapping['support_entities']]
       
   390             if not rschema in mapping['support_relations']:
       
   391                 somethingprinted = False
       
   392                 for ttype in ttypes:
       
   393                     rdef = rschema.role_rdef(eschema, ttype, role)
       
   394                     seen.add(rdef)
       
   395                     if rdef.role_cardinality(role) in '1+':
       
   396                         error('relation %s with %s as %s and target type %s is '
       
   397                               'mandatory but not supported',
       
   398                               rschema, eschema, role, ttype)
       
   399                         somethingprinted = True
       
   400                     elif ttype in mapping['support_entities']:
       
   401                         if rdef not in seen:
       
   402                             warning('%s could be supported', rdef)
       
   403                         somethingprinted = True
       
   404                 if rschema not in mapping['dont_cross_relations']:
       
   405                     if role == 'subject' and rschema.inlined:
       
   406                         error('inlined relation %s of %s should be supported',
       
   407                               rschema, eschema)
       
   408                     elif not somethingprinted and rschema not in seen:
       
   409                         print 'you may want to specify something for %s' % rschema
       
   410                         seen.add(rschema)
       
   411             elif not ttypes:
       
   412                 warning('relation %s with %s as %s is supported but no target '
       
   413                         'type supported', rschema, role, eschema)
       
   414     for rschema in mapping['support_relations'].values():
       
   415         if rschema in META_RTYPES:
       
   416             continue
       
   417         for subj, obj in rschema.rdefs:
       
   418             if subj in mapping['support_entities'] and obj in mapping['support_entities']:
       
   419                 break
       
   420         else:
       
   421             error('relation %s is supported but none if its definitions '
       
   422                   'matches supported entities', rschema)