186 self.system_source = self.get_source('native', 'system', |
186 self.system_source = self.get_source('native', 'system', |
187 config.system_source_config.copy()) |
187 config.system_source_config.copy()) |
188 self.sources_by_uri = {'system': self.system_source} |
188 self.sources_by_uri = {'system': self.system_source} |
189 # querier helper, need to be created after sources initialization |
189 # querier helper, need to be created after sources initialization |
190 self.querier = querier.QuerierHelper(self, self.schema) |
190 self.querier = querier.QuerierHelper(self, self.schema) |
191 # cache eid -> (type, physical source, extid, actual source) |
191 # cache eid -> (type, extid, actual source) |
192 self._type_source_cache = {} |
192 self._type_source_cache = {} |
193 # cache (extid, source uri) -> eid |
193 # cache extid -> eid |
194 self._extid_cache = {} |
194 self._extid_cache = {} |
195 # open some connection sets |
195 # open some connection sets |
196 if config.init_cnxset_pool: |
196 if config.init_cnxset_pool: |
197 self.init_cnxset_pool() |
197 self.init_cnxset_pool() |
198 # the hooks manager |
198 # the hooks manager |
726 self.exception('unexpected error while executing %s with %s', rqlstring, args) |
726 self.exception('unexpected error while executing %s with %s', rqlstring, args) |
727 raise |
727 raise |
728 finally: |
728 finally: |
729 session.free_cnxset() |
729 session.free_cnxset() |
730 |
730 |
|
731 @deprecated('[3.19] use .entity_metas(sessionid, eid, txid) instead') |
731 def describe(self, sessionid, eid, txid=None): |
732 def describe(self, sessionid, eid, txid=None): |
732 """return a tuple `(type, physical source uri, extid, actual source |
733 """return a tuple `(type, physical source uri, extid, actual source |
733 uri)` for the entity of the given `eid` |
734 uri)` for the entity of the given `eid` |
|
735 |
|
736 As of 3.19, physical source uri is always the system source. |
734 """ |
737 """ |
735 session = self._get_session(sessionid, setcnxset=True, txid=txid) |
738 session = self._get_session(sessionid, setcnxset=True, txid=txid) |
736 try: |
739 try: |
737 return self.type_and_source_from_eid(eid, session) |
740 etype, extid, source = self.type_and_source_from_eid(eid, session) |
|
741 return etype, source, extid, source |
|
742 finally: |
|
743 session.free_cnxset() |
|
744 |
|
745 def entity_metas(self, sessionid, eid, txid=None): |
|
746 """return a dictionary containing meta-datas for the entity of the given |
|
747 `eid`. Available keys are: |
|
748 |
|
749 * 'type', the entity's type name, |
|
750 |
|
751 * 'source', the name of the source from which this entity's coming from, |
|
752 |
|
753 * 'extid', the identifierfor this entity in its originating source, as |
|
754 an encoded string or `None` for entities from the 'system' source. |
|
755 """ |
|
756 session = self._get_session(sessionid, setcnxset=True, txid=txid) |
|
757 try: |
|
758 etype, extid, source = self.type_and_source_from_eid(eid, session) |
|
759 return {'type': etype, 'source': source, 'extid': extid} |
738 finally: |
760 finally: |
739 session.free_cnxset() |
761 session.free_cnxset() |
740 |
762 |
741 def check_session(self, sessionid): |
763 def check_session(self, sessionid): |
742 """raise `BadConnectionId` if the connection is no more valid, else |
764 """raise `BadConnectionId` if the connection is no more valid, else |
932 # data sources handling ################################################### |
954 # data sources handling ################################################### |
933 # * correspondance between eid and (type, source) |
955 # * correspondance between eid and (type, source) |
934 # * correspondance between eid and local id (i.e. specific to a given source) |
956 # * correspondance between eid and local id (i.e. specific to a given source) |
935 |
957 |
936 def type_and_source_from_eid(self, eid, session=None): |
958 def type_and_source_from_eid(self, eid, session=None): |
937 """return a tuple `(type, physical source uri, extid, actual source |
959 """return a tuple `(type, extid, actual source uri)` for the entity of |
938 uri)` for the entity of the given `eid` |
960 the given `eid` |
939 """ |
961 """ |
940 try: |
962 try: |
941 eid = int(eid) |
963 eid = int(eid) |
942 except ValueError: |
964 except ValueError: |
943 raise UnknownEid(eid) |
965 raise UnknownEid(eid) |
948 session = self.internal_session() |
970 session = self.internal_session() |
949 free_cnxset = True |
971 free_cnxset = True |
950 else: |
972 else: |
951 free_cnxset = False |
973 free_cnxset = False |
952 try: |
974 try: |
953 etype, uri, extid, auri = self.system_source.eid_type_source( |
975 etype, extid, auri = self.system_source.eid_type_source( |
954 session, eid) |
976 session, eid) |
955 finally: |
977 finally: |
956 if free_cnxset: |
978 if free_cnxset: |
957 session.free_cnxset() |
979 session.free_cnxset() |
958 self._type_source_cache[eid] = (etype, uri, extid, auri) |
980 self._type_source_cache[eid] = (etype, extid, auri) |
959 if uri != 'system': |
981 return etype, extid, auri |
960 self._extid_cache[(extid, uri)] = eid |
|
961 return etype, uri, extid, auri |
|
962 |
982 |
963 def clear_caches(self, eids): |
983 def clear_caches(self, eids): |
964 etcache = self._type_source_cache |
984 etcache = self._type_source_cache |
965 extidcache = self._extid_cache |
985 extidcache = self._extid_cache |
966 rqlcache = self.querier._rql_cache |
986 rqlcache = self.querier._rql_cache |
967 for eid in eids: |
987 for eid in eids: |
968 try: |
988 try: |
969 etype, uri, extid, auri = etcache.pop(int(eid)) # may be a string in some cases |
989 etype, extid, auri = etcache.pop(int(eid)) # may be a string in some cases |
970 rqlcache.pop( ('%s X WHERE X eid %s' % (etype, eid),), None) |
990 rqlcache.pop( ('%s X WHERE X eid %s' % (etype, eid),), None) |
971 extidcache.pop((extid, uri), None) |
991 extidcache.pop(extid, None) |
972 except KeyError: |
992 except KeyError: |
973 etype = None |
993 etype = None |
974 rqlcache.pop( ('Any X WHERE X eid %s' % eid,), None) |
994 rqlcache.pop( ('Any X WHERE X eid %s' % eid,), None) |
975 self.system_source.clear_eid_cache(eid, etype) |
995 self.system_source.clear_eid_cache(eid, etype) |
976 |
996 |
977 def type_from_eid(self, eid, session=None): |
997 def type_from_eid(self, eid, session=None): |
978 """return the type of the entity with id <eid>""" |
998 """return the type of the entity with id <eid>""" |
979 return self.type_and_source_from_eid(eid, session)[0] |
999 return self.type_and_source_from_eid(eid, session)[0] |
980 |
|
981 def source_from_eid(self, eid, session=None): |
|
982 """return the source for the given entity's eid""" |
|
983 return self.sources_by_uri[self.type_and_source_from_eid(eid, session)[1]] |
|
984 |
1000 |
985 def querier_cache_key(self, session, rql, args, eidkeys): |
1001 def querier_cache_key(self, session, rql, args, eidkeys): |
986 cachekey = [rql] |
1002 cachekey = [rql] |
987 for key in sorted(eidkeys): |
1003 for key in sorted(eidkeys): |
988 try: |
1004 try: |
995 cachekey.append(etype) |
1011 cachekey.append(etype) |
996 # ensure eid is correctly typed in args |
1012 # ensure eid is correctly typed in args |
997 args[key] = int(args[key]) |
1013 args[key] = int(args[key]) |
998 return tuple(cachekey) |
1014 return tuple(cachekey) |
999 |
1015 |
1000 def eid2extid(self, source, eid, session=None): |
|
1001 """get local id from an eid""" |
|
1002 etype, uri, extid, _ = self.type_and_source_from_eid(eid, session) |
|
1003 if source.uri != uri: |
|
1004 # eid not from the given source |
|
1005 raise UnknownEid(eid) |
|
1006 return extid |
|
1007 |
|
1008 def extid2eid(self, source, extid, etype, session=None, insert=True, |
1016 def extid2eid(self, source, extid, etype, session=None, insert=True, |
1009 complete=True, commit=True, sourceparams=None): |
1017 complete=True, commit=True, sourceparams=None): |
1010 """Return eid from a local id. If the eid is a negative integer, that |
1018 """Return eid from a local id. If the eid is a negative integer, that |
1011 means the entity is known but has been copied back to the system source |
1019 means the entity is known but has been copied back to the system source |
1012 hence should be ignored. |
1020 hence should be ignored. |
1027 complete building of the entity instance |
1035 complete building of the entity instance |
1028 |
1036 |
1029 6. unless source's :attr:`should_call_hooks` tell otherwise, |
1037 6. unless source's :attr:`should_call_hooks` tell otherwise, |
1030 'before_add_entity' hooks are called |
1038 'before_add_entity' hooks are called |
1031 """ |
1039 """ |
1032 uri = 'system' |
1040 try: |
1033 cachekey = (extid, uri) |
1041 return self._extid_cache[extid] |
1034 try: |
|
1035 return self._extid_cache[cachekey] |
|
1036 except KeyError: |
1042 except KeyError: |
1037 pass |
1043 pass |
1038 free_cnxset = False |
1044 free_cnxset = False |
1039 if session is None: |
1045 if session is None: |
1040 session = self.internal_session() |
1046 session = self.internal_session() |
1041 free_cnxset = True |
1047 free_cnxset = True |
1042 eid = self.system_source.extid2eid(session, uri, extid) |
1048 eid = self.system_source.extid2eid(session, extid) |
1043 if eid is not None: |
1049 if eid is not None: |
1044 self._extid_cache[cachekey] = eid |
1050 self._extid_cache[extid] = eid |
1045 self._type_source_cache[eid] = (etype, uri, extid, source.uri) |
1051 self._type_source_cache[eid] = (etype, extid, source.uri) |
1046 if free_cnxset: |
1052 if free_cnxset: |
1047 session.free_cnxset() |
1053 session.free_cnxset() |
1048 return eid |
1054 return eid |
1049 if not insert: |
1055 if not insert: |
1050 return |
1056 return |
1057 if not session.is_internal_session: |
1063 if not session.is_internal_session: |
1058 session = self.internal_session() |
1064 session = self.internal_session() |
1059 free_cnxset = True |
1065 free_cnxset = True |
1060 try: |
1066 try: |
1061 eid = self.system_source.create_eid(session) |
1067 eid = self.system_source.create_eid(session) |
1062 self._extid_cache[cachekey] = eid |
1068 self._extid_cache[extid] = eid |
1063 self._type_source_cache[eid] = (etype, uri, extid, source.uri) |
1069 self._type_source_cache[eid] = (etype, extid, source.uri) |
1064 entity = source.before_entity_insertion( |
1070 entity = source.before_entity_insertion( |
1065 session, extid, etype, eid, sourceparams) |
1071 session, extid, etype, eid, sourceparams) |
1066 if source.should_call_hooks: |
1072 if source.should_call_hooks: |
1067 # get back a copy of operation for later restore if necessary, |
1073 # get back a copy of operation for later restore if necessary, |
1068 # see below |
1074 # see below |
1079 if commit or free_cnxset: |
1085 if commit or free_cnxset: |
1080 session.rollback(free_cnxset) |
1086 session.rollback(free_cnxset) |
1081 else: |
1087 else: |
1082 # XXX do some cleanup manually so that the transaction has a |
1088 # XXX do some cleanup manually so that the transaction has a |
1083 # chance to be commited, with simply this entity discarded |
1089 # chance to be commited, with simply this entity discarded |
1084 self._extid_cache.pop(cachekey, None) |
1090 self._extid_cache.pop(extid, None) |
1085 self._type_source_cache.pop(eid, None) |
1091 self._type_source_cache.pop(eid, None) |
1086 if 'entity' in locals(): |
1092 if 'entity' in locals(): |
1087 hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid) |
1093 hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid) |
1088 self.system_source.delete_info_multi(session, [entity]) |
1094 self.system_source.delete_info_multi(session, [entity]) |
1089 if source.should_call_hooks: |
1095 if source.should_call_hooks: |
1175 def init_entity_caches(self, session, entity, source): |
1181 def init_entity_caches(self, session, entity, source): |
1176 """add entity to session entities cache and repo's extid cache. |
1182 """add entity to session entities cache and repo's extid cache. |
1177 Return entity's ext id if the source isn't the system source. |
1183 Return entity's ext id if the source isn't the system source. |
1178 """ |
1184 """ |
1179 session.set_entity_cache(entity) |
1185 session.set_entity_cache(entity) |
1180 suri = source.uri |
1186 if source.uri == 'system': |
1181 if suri == 'system': |
|
1182 extid = None |
1187 extid = None |
1183 else: |
1188 else: |
1184 suri = 'system' |
|
1185 extid = source.get_extid(entity) |
1189 extid = source.get_extid(entity) |
1186 self._extid_cache[(str(extid), suri)] = entity.eid |
1190 self._extid_cache[str(extid)] = entity.eid |
1187 self._type_source_cache[entity.eid] = (entity.cw_etype, suri, extid, |
1191 self._type_source_cache[entity.eid] = (entity.cw_etype, extid, source.uri) |
1188 source.uri) |
|
1189 return extid |
1192 return extid |
1190 |
1193 |
1191 def glob_add_entity(self, session, edited): |
1194 def glob_add_entity(self, session, edited): |
1192 """add an entity to the repository |
1195 """add an entity to the repository |
1193 |
1196 |