ATLAS Offline Software
Loading...
Searching...
No Matches
clidGenerator.py
Go to the documentation of this file.
1# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
2
3
7import string, re, os, csv
8
9# CLID assignment was originally based on the builtin hash() function.
10# However, the results of that are not standardized, and in fact changed
11# between py2 and py3. (In py3, hash(s) can return differing values
12# from run to run.) This is an implementation of the py2 string hashing
13# algorithm, so we can give the same results for py2 vs. py3.
14def py2_hash (s):
15 if len(s) == 0: return 0
16 x = ord(s[0]) << 7
17 for c in s:
18 x = (1000003*x) ^ ord(c)
19 x ^= len(s)
20 x &= 0xffffffff
21 if x == 0xffffffff:
22 x = 0xfffffffe
23 return x
24
25
27 """Athena CLID Generator"""
28 # CLID Mask: Determines bits used for CLID
29 __mask = 0x0FFFFFFF
30 # CLID Repositories - Dictionaries of CLID<=>Name
31 __clidRep = {} # Lookup by CLID
32 __clidTid = {} # Lookup by CLID
33 __nameRep = {} # Lookup by ClassName
34 __tidRep = {} # Lookup by typeid-name
35
36 def __init__(self, db, debug=False):
37 self.setCLIDDB(db, debug)
38 self.readdb()
39
40 def cleardb(self):
41 clidGenerator.__clidRep = {} # Lookup by CLID
42 clidGenerator.__nameRep = {} # Lookup by ClassName
43
44 def readdb(self):
45 """Read CLID DataBase file"""
46 try:
47 for cliddb in self.__cliddbs:
48 if os.path.isfile(cliddb):
49 with open(cliddb, 'r') as f_cliddb:
50 for row in csv.reader (f_cliddb, delimiter=';'):
51 row = [i.strip() for i in row]
52 if len(row) >= 2:
53 clid = int(row[0])
54 class_name = row[1]
55 tid_name = row[2] if len(row)>2 else class_name
56
57 self.__clidRep[clid] = class_name
58 self.__clidTid[clid] = tid_name
59 self.__nameRep[class_name] = clid
60 self.__tidRep [tid_name] = clid
61
62 else:
63 print ("No CLID DataBase file <%s> " % cliddb)
64 except Exception as err:
65 print ("Error reading from CLID DataBase files <%s>:\n%s " % (
66 self.__cliddbs,
67 err))
68
69 def setCLIDDB(self, db, debug):
70 """Initializes a CLID Generator object with a CLID Database"""
71 if db:
72 self.__cliddbs = search_files(db, os.getenv('DATAPATH'))
73 if debug: print ("Using specified CLID DataBase files %s " % self.__cliddbs)
74 elif os.getenv('CLIDDB'):
75 # CLID DataBase (Default = clid.db)
76 self.__cliddbs.append(os.getenv('CLIDDB'))
77 if debug: print ("Using DataBase file from CLIDDB env variable %s " % self.__cliddbs)
78 else:
79 self.__cliddbs = search_files('clid.db', os.getenv('DATAPATH'))
80 if debug: print ("Using DataBase file from DATAPATH %s " % self.__cliddbs)
81
82 def writedb(self,db):
83 """Read CLID DataBase file"""
84 output = open(db,'w')
85 for k in self.__clidRep.keys():
86 output.write("%d "%k+self.__clidRep[k]+"\n")
87 output.close()
88
89 def genClidFromName(self,className):
90 """Generate CLID from ClassName: A recursive hash with a bit
91 mask and validity range. Will check collisions against and
92 update CLID Repository."""
93 n = self.demangleClassName(className)
94 c = self.getClidFromName(className)
95 if c:
96 return c
97 c = py2_hash(className) & self.__mask
98 if c < 10001 or c > self.__mask:
99 c = self.genClidFromName(className+'_')
100 if self.isCollection(className):
101 c += 0x40000000
102 if c in self.__clidRep:
103 if n != self.__clidRep[c]:
104 c = self.genClidFromName(className+'_')
105 else:
106 self.__clidRep[c] = n
107 self.__clidTid[c] = n # make typeid name the same than class-name
108 self.__nameRep[n] = c
109 self.__tidRep [n] = c # idem
110 return c
111
112 def getClidFromName(self,className):
113 """Get the CLID in the repository of class name <className>"""
114 return self.__nameRep.get(className, None)
115
116 def getClidFromTid(self,tidName):
117 """Get the CLID in the repository of typeid name <tidName>"""
118 return self.__tidRep.get(tidName, None)
119
120 def getNameFromClid(self,clid):
121 """Get the class name in the repository with CLID <clid>"""
122 return self.__clidRep.get(clid, None)
123
124 def getTidFromClid(self,clid):
125 """Get the typeid name in the repository with CLID <clid>"""
126 return self.__clidTid.get(clid, None)
127
128 def demangleClassName(self,s):
129 return s
130# pat = re.compile('\s*(.?)__*\s*')
131# n = pat.findall(s)
132# if n:
133# return n[0]
134# else:
135# return s
136
137 def isCollection(self,className):
138 collMatch = re.search(r'.*?Collection_*|.*?Container_*',className)
139 return collMatch
140
141 def findPattern(self,s):
142 """Find the regular expression pattern s in dictionary."""
143# pat = re.compile('^'+s+'$')
144 pat = re.compile(s)
145 results = {}
146 for k in self.__clidRep.keys():
147 if pat.match(str(k)) or pat.match(self.__clidRep[k]):
148 results[k] = self.__clidRep[k]
149 return results
150
151def search_file(filename, search_path, pathsep=os.pathsep):
152 """Given a search path, find file with requested name """
153 for path in string.split(search_path, pathsep):
154 candidate = os.path.join(path, filename)
155 if os.path.exists(candidate): return os.path.abspath(candidate)
156 return None
157
158def search_files(filename, search_path, pathsep=os.pathsep):
159 """Given a search path, find file with requested name """
160 clidFiles = []
161 for path in search_path.split(pathsep):
162 candidate = os.path.join(path, filename)
163 if os.path.exists(candidate): clidFiles.append(os.path.abspath(candidate))
164 return clidFiles
Athena CLID Generator Class.