diff -r 6fa712e9dfa5 -r 0af44a38fe41 server/sources/native.py --- a/server/sources/native.py Mon Jan 24 19:09:42 2011 +0100 +++ b/server/sources/native.py Tue Feb 01 11:52:10 2011 +0100 @@ -35,6 +35,7 @@ from contextlib import contextmanager from os.path import abspath import re +import itertools from logilab.common.compat import any from logilab.common.cache import Cache @@ -553,23 +554,29 @@ # on the filesystem. To make the entity.data usage absolutely # transparent, we'll have to reset entity.data to its binary # value once the SQL query will be executed - restore_values = {} - etype = entity.__regid__ + restore_values = [] + if isinstance(entity, list): + entities = entity + else: + entities = [entity] + etype = entities[0].__regid__ for attr, storage in self._storages.get(etype, {}).items(): - try: - edited = entity.cw_edited - except AttributeError: - assert event == 'deleted' - getattr(storage, 'entity_deleted')(entity, attr) - else: - if attr in edited: - handler = getattr(storage, 'entity_%s' % event) - restore_values[attr] = handler(entity, attr) + for entity in entities: + try: + edited = entity.cw_edited + except AttributeError: + assert event == 'deleted' + getattr(storage, 'entity_deleted')(entity, attr) + else: + if attr in edited: + handler = getattr(storage, 'entity_%s' % event) + to_restore = handler(entity, attr) + restore_values.append((entity, attr, to_restore)) try: yield # 2/ execute the source's instructions finally: # 3/ restore original values - for attr, value in restore_values.items(): + for entity, attr, value in restore_values: entity.cw_edited.edited_attribute(attr, value) def add_entity(self, session, entity): @@ -923,7 +930,7 @@ * transfer it to the deleted_entities table if the entity's type is multi-sources """ - self.fti_unindex_entity(session, entity.eid) + self.fti_unindex_entities(session, [entity]) attrs = {'eid': entity.eid} self.doexec(session, self.sqlgen.delete('entities', attrs), attrs) if not entity.__regid__ in self.multisources_etypes: @@ -935,6 +942,27 @@ 'source': uri, 'dtime': datetime.now()} self.doexec(session, self.sqlgen.insert('deleted_entities', attrs), attrs) + def delete_info_multi(self, session, entities, uri, extids): + """delete system information on deletion of an entity: + * update the fti + * remove record from the entities table + * transfer it to the deleted_entities table if the entity's type is + multi-sources + """ + self.fti_unindex_entities(session, entities) + attrs = {'eid': '(%s)' % ','.join([str(_e.eid) for _e in entities])} + self.doexec(session, self.sqlgen.delete_many('entities', attrs), attrs) + if entities[0].__regid__ not in self.multisources_etypes: + return + attrs = {'type': entities[0].__regid__, + 'source': uri, 'dtime': datetime.now()} + for entity, extid in itertools.izip(entities, extids): + if extid is not None: + assert isinstance(extid, str), type(extid) + extid = b64encode(extid) + attrs.update({'eid': entity.eid, 'extid': extid}) + self.doexec(session, self.sqlgen.insert('deleted_entities', attrs), attrs) + def modified_entities(self, session, etypes, mtime): """return a 2-uple: * list of (etype, eid) of entities of the given types which have been @@ -1302,27 +1330,32 @@ """ FTIndexEntityOp.get_instance(session).add_data(entity.eid) - def fti_unindex_entity(self, session, eid): - """remove text content for entity with the given eid from the full text - index + def fti_unindex_entities(self, session, entities): + """remove text content for entities from the full text index """ + cursor = session.pool['system'] + cursor_unindex_object = self.dbhelper.cursor_unindex_object try: - self.dbhelper.cursor_unindex_object(eid, session.pool['system']) + for entity in entities: + cursor_unindex_object(entity.eid, cursor) except Exception: # let KeyboardInterrupt / SystemExit propagate - self.exception('error while unindexing %s', eid) + self.exception('error while unindexing %s', entity) + - def fti_index_entity(self, session, entity): - """add text content of a created/modified entity to the full text index + def fti_index_entities(self, session, entities): + """add text content of created/modified entities to the full text index """ - self.debug('reindexing %r', entity.eid) + cursor_index_object = self.dbhelper.cursor_index_object + cursor = session.pool['system'] try: # use cursor_index_object, not cursor_reindex_object since # unindexing done in the FTIndexEntityOp - self.dbhelper.cursor_index_object(entity.eid, - entity.cw_adapt_to('IFTIndexable'), - session.pool['system']) + for entity in entities: + cursor_index_object(entity.eid, + entity.cw_adapt_to('IFTIndexable'), + cursor) except Exception: # let KeyboardInterrupt / SystemExit propagate - self.exception('error while reindexing %s', entity) + self.exception('error while indexing %s', entity) class FTIndexEntityOp(hook.DataOperationMixIn, hook.LateOperation): @@ -1338,17 +1371,17 @@ source = session.repo.system_source pendingeids = session.transaction_data.get('pendingeids', ()) done = session.transaction_data.setdefault('indexedeids', set()) + to_reindex = set() for eid in self.get_data(): if eid in pendingeids or eid in done: # entity added and deleted in the same transaction or already # processed - return + continue done.add(eid) iftindexable = session.entity_from_eid(eid).cw_adapt_to('IFTIndexable') - for container in iftindexable.fti_containers(): - source.fti_unindex_entity(session, container.eid) - source.fti_index_entity(session, container) - + to_reindex |= set(iftindexable.fti_containers()) + source.fti_unindex_entities(session, to_reindex) + source.fti_index_entities(session, to_reindex) def sql_schema(driver): helper = get_db_helper(driver)