1 | package simulator.workload.reader.archive; |
---|
2 | |
---|
3 | import java.io.IOException; |
---|
4 | import java.io.RandomAccessFile; |
---|
5 | import java.util.HashMap; |
---|
6 | |
---|
7 | import org.apache.commons.logging.Log; |
---|
8 | import org.apache.commons.logging.LogFactory; |
---|
9 | |
---|
10 | import simulator.workload.exceptons.NoSuchCommentException; |
---|
11 | import simulator.workload.reader.archive.gwf.GWFParser; |
---|
12 | import simulator.workload.reader.archive.swf.SWFParser; |
---|
13 | |
---|
14 | /** |
---|
15 | * |
---|
16 | * @author Marcin Krystek |
---|
17 | * |
---|
18 | */ |
---|
19 | |
---|
20 | public abstract class AbstractWAParser extends RandomAccessFile implements WAParser { |
---|
21 | |
---|
22 | private Log log = LogFactory.getLog(AbstractWAParser.class); |
---|
23 | |
---|
24 | private static final long serialVersionUID = 1L; |
---|
25 | private String fileName; |
---|
26 | |
---|
27 | protected String COMMENT = ";"; |
---|
28 | protected String FIELD_SEPARATOR = "\\s"; //white spaces |
---|
29 | |
---|
30 | protected HashMap<String, String> comments; |
---|
31 | protected HashMap<String, String[]> idMapping; // key - swf job id, value - value[0] xml job id, value[1] xml task id |
---|
32 | protected HashMap<String, String> reverseIdMapping; // key - xmlJobId_xmlTaskId, value - swf job id |
---|
33 | protected HashMap<String, Long> jobIndex; |
---|
34 | protected String fields[]; |
---|
35 | protected int fieldsNo; |
---|
36 | protected boolean headerLoaded; |
---|
37 | protected boolean buildIndex; |
---|
38 | |
---|
39 | public AbstractWAParser(String fileName) throws IOException, NullPointerException{ |
---|
40 | super(fileName, "r"); |
---|
41 | this.fileName = fileName; |
---|
42 | this.comments = new HashMap<String, String>(); |
---|
43 | this.idMapping = new HashMap<String, String[]>(); |
---|
44 | this.reverseIdMapping = new HashMap<String, String>(); |
---|
45 | this.jobIndex = new HashMap<String, Long>(); |
---|
46 | this.headerLoaded = false; |
---|
47 | this.buildIndex = true; |
---|
48 | this.fieldsNo = 18; |
---|
49 | } |
---|
50 | |
---|
51 | |
---|
52 | /** |
---|
53 | * Reads one task description and returns all fields in table. |
---|
54 | * Skips comments lines, so you can mix task description with comments. |
---|
55 | */ |
---|
56 | public String[] readTask() throws IOException { |
---|
57 | String line = null; |
---|
58 | fields = null; |
---|
59 | |
---|
60 | while((line = readLine()) != null){ |
---|
61 | line = line.trim(); |
---|
62 | if(line.length() == 0 || line.startsWith(COMMENT)){ |
---|
63 | continue; |
---|
64 | } else{ |
---|
65 | fields = line.split(FIELD_SEPARATOR+"+"); |
---|
66 | |
---|
67 | if(fields == null || fields.length != fieldsNo) |
---|
68 | throw new IOException("Some data fields are missing."); |
---|
69 | else |
---|
70 | break; |
---|
71 | } |
---|
72 | |
---|
73 | } |
---|
74 | return fields; |
---|
75 | } |
---|
76 | |
---|
77 | |
---|
78 | public String[] readTask(String jobID, String taskId) throws IOException{ |
---|
79 | String key = jobID+"_"+taskId; |
---|
80 | String swfJobId; |
---|
81 | |
---|
82 | if(reverseIdMapping.containsKey(key)){ |
---|
83 | swfJobId = reverseIdMapping.get(key); |
---|
84 | } else { |
---|
85 | swfJobId = jobID; |
---|
86 | } |
---|
87 | |
---|
88 | return readTask(swfJobId); |
---|
89 | } |
---|
90 | |
---|
91 | public String getCommentValue(String label) throws NoSuchCommentException { |
---|
92 | if(!comments.containsKey(label)) |
---|
93 | throw new NoSuchCommentException("No comment value for "+label); |
---|
94 | |
---|
95 | return comments.get(label); |
---|
96 | } |
---|
97 | |
---|
98 | public String getDataField(int field) throws NoSuchFieldException { |
---|
99 | if(field >= fields.length) |
---|
100 | throw new NoSuchFieldException("No such field."); |
---|
101 | |
---|
102 | return fields[field]; |
---|
103 | } |
---|
104 | |
---|
105 | /** |
---|
106 | * Reads all comments that have appropriate format and place them in HashMap. |
---|
107 | * Builds job index - decision depends on value of buildIndex variable. |
---|
108 | */ |
---|
109 | public HashMap<String, String> loadHeader() throws IOException { |
---|
110 | String line = null; |
---|
111 | String label = null; |
---|
112 | String value = null; |
---|
113 | int idx = -1; |
---|
114 | |
---|
115 | |
---|
116 | // default speed for processing unit in millions of instructions. |
---|
117 | comments.put(WAFields.COMMENT_PUSPEED, "1"); |
---|
118 | |
---|
119 | long position = 0; |
---|
120 | while((position = super.getFilePointer()) != -1 && (line = readLine()) != null){ |
---|
121 | line = line.trim(); |
---|
122 | if(!line.startsWith(COMMENT)){ |
---|
123 | if(buildIndex){ |
---|
124 | buildIdx(line, position); |
---|
125 | } |
---|
126 | continue; |
---|
127 | } |
---|
128 | |
---|
129 | idx = line.indexOf(":"); |
---|
130 | if(idx == -1) |
---|
131 | continue; |
---|
132 | |
---|
133 | label = line.substring(1, idx); |
---|
134 | label = label.trim(); |
---|
135 | |
---|
136 | if(idx + 1 > line.length()) |
---|
137 | throw new IOException("No value for comment: "+label); |
---|
138 | |
---|
139 | value = line.substring(idx + 1, line.length()); |
---|
140 | value = value.trim(); |
---|
141 | |
---|
142 | if(label.equals(WAFields.COMMENT_NOTE) && comments.containsKey(label)){ |
---|
143 | value = comments.get(label)+"; "+value; |
---|
144 | } else if(label.equals(WAFields.COMMENT_IDMAPPING)){ |
---|
145 | loadIDMapping(); |
---|
146 | continue; |
---|
147 | } |
---|
148 | |
---|
149 | comments.put(label, value); |
---|
150 | } |
---|
151 | reset(); |
---|
152 | headerLoaded = true; |
---|
153 | return comments; |
---|
154 | } |
---|
155 | |
---|
156 | protected void loadIDMapping() throws IOException{ |
---|
157 | String line = null; |
---|
158 | |
---|
159 | while((line = readLine()) != null){ |
---|
160 | |
---|
161 | line = line.trim(); |
---|
162 | |
---|
163 | if(!line.startsWith(COMMENT)) |
---|
164 | continue; |
---|
165 | |
---|
166 | line = line.substring(1).trim(); // to cut beginning ';' |
---|
167 | if(line.startsWith(WAFields.COMMENT_IDMAPPING+": end")) |
---|
168 | break; |
---|
169 | |
---|
170 | String idsInLine[] = line.split(","); |
---|
171 | String third = null; |
---|
172 | String ids[] = null; |
---|
173 | |
---|
174 | for(int i = 0; i < idsInLine.length; i++){ |
---|
175 | third = idsInLine[i]; |
---|
176 | ids = third.split(":"); |
---|
177 | if(ids.length < 3){ |
---|
178 | if(ids.length != 1) |
---|
179 | if(log.isWarnEnabled()) |
---|
180 | log.warn(third + " is not complete. Use swfJobId:xmlJobId:xmlTaskId"); |
---|
181 | continue; |
---|
182 | } |
---|
183 | String key = ids[0].trim(); |
---|
184 | String value[] = new String[2]; |
---|
185 | value[0] = ids[1].trim(); // job id |
---|
186 | value[1] = ids[2].trim(); // task id |
---|
187 | idMapping.put(key, value); |
---|
188 | reverseIdMapping.put(value[0]+"_"+value[1], key); |
---|
189 | } |
---|
190 | |
---|
191 | } |
---|
192 | } |
---|
193 | |
---|
194 | /** |
---|
195 | * Sets comment sign. Default is ';'. |
---|
196 | */ |
---|
197 | public String setCommentSign(String comment) { |
---|
198 | String oldComment = this.COMMENT; |
---|
199 | this.COMMENT = comment; |
---|
200 | return oldComment; |
---|
201 | } |
---|
202 | |
---|
203 | /** |
---|
204 | * Sets data fields separator. Default is tab (\t). |
---|
205 | */ |
---|
206 | public String setFieldSeparator(String fieldSeparator) { |
---|
207 | String oldSeparator = this.FIELD_SEPARATOR; |
---|
208 | this.FIELD_SEPARATOR = fieldSeparator; |
---|
209 | return oldSeparator; |
---|
210 | } |
---|
211 | |
---|
212 | /** |
---|
213 | * Decide if task position index should be build. It is very useful |
---|
214 | * and significantly speedup |
---|
215 | * @return previous value |
---|
216 | */ |
---|
217 | public boolean buildIndex(boolean build){ |
---|
218 | boolean old = this.buildIndex; |
---|
219 | this.buildIndex = build; |
---|
220 | return old; |
---|
221 | } |
---|
222 | |
---|
223 | public void close() throws IOException { |
---|
224 | super.close(); |
---|
225 | this.comments.clear(); |
---|
226 | this.comments = null; |
---|
227 | this.idMapping.clear(); |
---|
228 | this.idMapping = null; |
---|
229 | this.reverseIdMapping.clear(); |
---|
230 | this.reverseIdMapping = null; |
---|
231 | this.jobIndex.clear(); |
---|
232 | this.jobIndex = null; |
---|
233 | } |
---|
234 | |
---|
235 | /** |
---|
236 | * Puts file pointer to the beginning of file. |
---|
237 | */ |
---|
238 | public void reset() throws IOException { |
---|
239 | super.seek(0); |
---|
240 | } |
---|
241 | |
---|
242 | public boolean isHeaderLoaded() { |
---|
243 | return headerLoaded; |
---|
244 | } |
---|
245 | |
---|
246 | public HashMap<String, String[]> getIDMapping(){ |
---|
247 | return this.idMapping; |
---|
248 | } |
---|
249 | |
---|
250 | |
---|
251 | public String[] getIDMapping(String waID) { |
---|
252 | |
---|
253 | if(idMapping.containsKey(waID)){ |
---|
254 | return this.idMapping.get(waID); |
---|
255 | } |
---|
256 | else { // if mapping for job is not provided, then we assume that xmlJobId, xmlTaskId, swfJobId are equal. |
---|
257 | String tab[] = {waID, waID}; |
---|
258 | return tab; |
---|
259 | } |
---|
260 | } |
---|
261 | |
---|
262 | |
---|
263 | public String getFileName(){ |
---|
264 | return this.fileName; |
---|
265 | } |
---|
266 | |
---|
267 | protected abstract void buildIdx(String line, long position); |
---|
268 | |
---|
269 | public static WAParser getInstance(String fileName){ |
---|
270 | String name = fileName.trim().toLowerCase(); |
---|
271 | |
---|
272 | try { |
---|
273 | |
---|
274 | if(name.endsWith("swf")){ |
---|
275 | return new SWFParser(fileName); |
---|
276 | |
---|
277 | } else if(name.endsWith("gwf")){ |
---|
278 | return new GWFParser(fileName); |
---|
279 | } |
---|
280 | |
---|
281 | } catch(Exception e){ |
---|
282 | e.printStackTrace(); |
---|
283 | } |
---|
284 | |
---|
285 | return null; |
---|
286 | } |
---|
287 | } |
---|