|
27 | 27 | import java.nio.channels.OverlappingFileLockException; |
28 | 28 | import java.nio.charset.StandardCharsets; |
29 | 29 | import java.nio.file.StandardOpenOption; |
| 30 | +import java.text.DecimalFormat; |
| 31 | +import java.time.Duration; |
| 32 | +import java.time.ZonedDateTime; |
| 33 | +import java.time.format.DateTimeFormatter; |
30 | 34 | import java.util.ArrayList; |
31 | 35 | import java.util.Date; |
32 | 36 | import java.util.HashMap; |
@@ -82,158 +86,189 @@ public SnapshotEntry(int usageCount, ISnapshot snapshot) |
82 | 86 |
|
83 | 87 | public ISnapshot openSnapshot(File file, Map<String, String> args, IProgressListener listener) throws SnapshotException |
84 | 88 | { |
85 | | - ISnapshot answer = null; |
| 89 | + ZonedDateTime start = ZonedDateTime.now(); |
| 90 | + listener.sendUserMessage( |
| 91 | + Severity.INFO, MessageUtil.format(Messages.SnapshotFactoryImpl_StartOpeningDump, |
| 92 | + file.getAbsolutePath(), DateTimeFormatter.ISO_ZONED_DATE_TIME.format(start)), |
| 93 | + null); |
86 | 94 |
|
87 | | - // lookup in cache |
88 | | - SnapshotEntry entry = snapshotCache.get(file); |
89 | | - if (entry != null) |
| 95 | + try |
90 | 96 | { |
91 | | - answer = entry.snapshot.get(); |
| 97 | + ISnapshot answer = null; |
92 | 98 |
|
93 | | - if (answer != null) |
| 99 | + // lookup in cache |
| 100 | + SnapshotEntry entry = snapshotCache.get(file); |
| 101 | + if (entry != null) |
94 | 102 | { |
95 | | - entry.usageCount++; |
96 | | - return answer; |
| 103 | + answer = entry.snapshot.get(); |
| 104 | + |
| 105 | + if (answer != null) |
| 106 | + { |
| 107 | + entry.usageCount++; |
| 108 | + return answer; |
| 109 | + } |
97 | 110 | } |
98 | | - } |
99 | 111 |
|
100 | | - String name = file.getName(); |
| 112 | + String name = file.getName(); |
101 | 113 |
|
102 | | - /* |
103 | | - * Perhaps there are extensions with dots, e.g. .phd.gz or .hprof.gz, |
104 | | - * so this code ensures the whole extension is removed. |
105 | | - */ |
106 | | - IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); |
107 | | - IContentType javaheapdump = contentTypeManager.getContentType("org.eclipse.mat.JavaHeapDump"); //$NON-NLS-1$ |
108 | | - List<IContentType>listtypes = new ArrayList<IContentType>(); |
109 | | - if (javaheapdump != null) |
110 | | - { |
111 | | - String n1 = name; |
112 | | - IContentType types[]; |
113 | | - try (FileInputStream fis = new FileInputStream(file)) |
114 | | - { |
115 | | - types = contentTypeManager.findContentTypesFor(fis, file.getPath()); |
116 | | - if (types.length == 0) |
| 114 | + /* |
| 115 | + * Perhaps there are extensions with dots, e.g. .phd.gz or |
| 116 | + * .hprof.gz, so this code ensures the whole extension is removed. |
| 117 | + */ |
| 118 | + IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); |
| 119 | + IContentType javaheapdump = contentTypeManager.getContentType("org.eclipse.mat.JavaHeapDump"); //$NON-NLS-1$ |
| 120 | + List<IContentType> listtypes = new ArrayList<IContentType>(); |
| 121 | + if (javaheapdump != null) |
| 122 | + { |
| 123 | + String n1 = name; |
| 124 | + IContentType types[]; |
| 125 | + try (FileInputStream fis = new FileInputStream(file)) |
117 | 126 | { |
118 | | - try (FileInputStream fis2 = new FileInputStream(file)) |
| 127 | + types = contentTypeManager.findContentTypesFor(fis, file.getPath()); |
| 128 | + if (types.length == 0) |
119 | 129 | { |
120 | | - types = contentTypeManager.findContentTypesFor(fis2, null); |
| 130 | + try (FileInputStream fis2 = new FileInputStream(file)) |
| 131 | + { |
| 132 | + types = contentTypeManager.findContentTypesFor(fis2, null); |
| 133 | + } |
121 | 134 | } |
122 | 135 | } |
123 | | - } |
124 | | - catch (IOException e) |
125 | | - { |
126 | | - // Ignore, try using file name alone |
127 | | - types = contentTypeManager.findContentTypesFor(file.getPath()); |
128 | | - } |
129 | | - for (IContentType tp : types) |
130 | | - { |
131 | | - if (tp.isKindOf(javaheapdump)) |
| 136 | + catch (IOException e) |
132 | 137 | { |
133 | | - // See if this content description is based on the file contents |
134 | | - IContentDescription cd1, cd2; |
135 | | - try (FileInputStream fis = new FileInputStream(file)) |
136 | | - { |
137 | | - // Succeeds if based on context |
138 | | - cd1 = tp.getDescriptionFor(fis, IContentDescription.ALL); |
139 | | - } |
140 | | - catch (IOException e) |
141 | | - { |
142 | | - cd1 = null; |
143 | | - } |
144 | | - try (InputStream sr = new ByteArrayInputStream(new byte[10])) |
145 | | - { |
146 | | - // Succeeds if generic type without content checking |
147 | | - cd2 = tp.getDescriptionFor(sr, IContentDescription.ALL); |
148 | | - } |
149 | | - catch (IOException e) |
150 | | - { |
151 | | - cd2 = null; |
152 | | - } |
153 | | - if (cd1 != null && cd2 == null) |
| 138 | + // Ignore, try using file name alone |
| 139 | + types = contentTypeManager.findContentTypesFor(file.getPath()); |
| 140 | + } |
| 141 | + for (IContentType tp : types) |
| 142 | + { |
| 143 | + if (tp.isKindOf(javaheapdump)) |
154 | 144 | { |
155 | | - listtypes.add(tp); |
156 | | - for (String ext: tp.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)) |
| 145 | + // See if this content description is based on the file |
| 146 | + // contents |
| 147 | + IContentDescription cd1, cd2; |
| 148 | + try (FileInputStream fis = new FileInputStream(file)) |
| 149 | + { |
| 150 | + // Succeeds if based on context |
| 151 | + cd1 = tp.getDescriptionFor(fis, IContentDescription.ALL); |
| 152 | + } |
| 153 | + catch (IOException e) |
| 154 | + { |
| 155 | + cd1 = null; |
| 156 | + } |
| 157 | + try (InputStream sr = new ByteArrayInputStream(new byte[10])) |
| 158 | + { |
| 159 | + // Succeeds if generic type without content checking |
| 160 | + cd2 = tp.getDescriptionFor(sr, IContentDescription.ALL); |
| 161 | + } |
| 162 | + catch (IOException e) |
157 | 163 | { |
158 | | - // Does extension itself contains a dot, and matches this file ? |
159 | | - if (ext.indexOf('.') >= 0 && name.endsWith("." + ext)) //$NON-NLS-1$ |
| 164 | + cd2 = null; |
| 165 | + } |
| 166 | + if (cd1 != null && cd2 == null) |
| 167 | + { |
| 168 | + listtypes.add(tp); |
| 169 | + for (String ext : tp.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)) |
160 | 170 | { |
161 | | - // It has a dot, so remove |
162 | | - n1 = name.substring(0, name.length() - ext.length()); |
163 | | - // This looks a good content type as matches with long extension. |
164 | | - // So put it first. |
165 | | - listtypes.remove(tp); |
166 | | - listtypes.add(0, tp); |
| 171 | + // Does extension itself contains a dot, and |
| 172 | + // matches this file ? |
| 173 | + if (ext.indexOf('.') >= 0 && name.endsWith("." + ext)) //$NON-NLS-1$ |
| 174 | + { |
| 175 | + // It has a dot, so remove |
| 176 | + n1 = name.substring(0, name.length() - ext.length()); |
| 177 | + // This looks a good content type as matches |
| 178 | + // with long extension. |
| 179 | + // So put it first. |
| 180 | + listtypes.remove(tp); |
| 181 | + listtypes.add(0, tp); |
| 182 | + } |
167 | 183 | } |
168 | 184 | } |
169 | 185 | } |
170 | 186 | } |
| 187 | + name = n1; |
171 | 188 | } |
172 | | - name = n1; |
173 | | - } |
174 | 189 |
|
175 | | - int p = name.lastIndexOf('.'); |
176 | | - name = p >= 0 ? name.substring(0, p + 1) : name + ".";//$NON-NLS-1$ |
177 | | - String prefix = new File(file.getParentFile(), name).getAbsolutePath(); |
178 | | - String snapshot_identifier = args.get("snapshot_identifier"); //$NON-NLS-1$ |
179 | | - if (snapshot_identifier != null) |
180 | | - { |
181 | | - prefix += snapshot_identifier + "."; //$NON-NLS-1$ |
182 | | - } |
| 190 | + int p = name.lastIndexOf('.'); |
| 191 | + name = p >= 0 ? name.substring(0, p + 1) : name + ".";//$NON-NLS-1$ |
| 192 | + String prefix = new File(file.getParentFile(), name).getAbsolutePath(); |
| 193 | + String snapshot_identifier = args.get("snapshot_identifier"); //$NON-NLS-1$ |
| 194 | + if (snapshot_identifier != null) |
| 195 | + { |
| 196 | + prefix += snapshot_identifier + "."; //$NON-NLS-1$ |
| 197 | + } |
183 | 198 |
|
184 | | - try |
185 | | - { |
186 | | - File indexFile = new File(prefix + "index");//$NON-NLS-1$ |
187 | | - if (indexFile.exists()) |
| 199 | + try |
188 | 200 | { |
189 | | - // check if hprof file is newer than index file |
190 | | - if (file.lastModified() <= indexFile.lastModified()) |
191 | | - { |
192 | | - answer = SnapshotImpl.readFromFile(file, prefix, listener); |
193 | | - } |
194 | | - else |
| 201 | + File indexFile = new File(prefix + "index");//$NON-NLS-1$ |
| 202 | + if (indexFile.exists()) |
195 | 203 | { |
196 | | - String message = MessageUtil.format(Messages.SnapshotFactoryImpl_ReparsingHeapDumpAsIndexOutOfDate, |
197 | | - file.getPath(), new Date(file.lastModified()), |
198 | | - indexFile.getPath(), new Date(indexFile.lastModified())); |
199 | | - listener.sendUserMessage(Severity.INFO, message, null); |
200 | | - listener.subTask(Messages.SnapshotFactoryImpl_ReparsingHeapDumpWithOutOfDateIndex); |
| 204 | + // check if hprof file is newer than index file |
| 205 | + if (file.lastModified() <= indexFile.lastModified()) |
| 206 | + { |
| 207 | + answer = SnapshotImpl.readFromFile(file, prefix, listener); |
| 208 | + } |
| 209 | + else |
| 210 | + { |
| 211 | + String message = MessageUtil.format( |
| 212 | + Messages.SnapshotFactoryImpl_ReparsingHeapDumpAsIndexOutOfDate, file.getPath(), |
| 213 | + new Date(file.lastModified()), indexFile.getPath(), |
| 214 | + new Date(indexFile.lastModified())); |
| 215 | + listener.sendUserMessage(Severity.INFO, message, null); |
| 216 | + listener.subTask(Messages.SnapshotFactoryImpl_ReparsingHeapDumpWithOutOfDateIndex); |
| 217 | + } |
201 | 218 | } |
202 | 219 | } |
203 | | - } |
204 | | - catch (IOException ignore_and_reparse) |
205 | | - { |
206 | | - String text = ignore_and_reparse.getMessage() != null ? ignore_and_reparse.getMessage() |
207 | | - : ignore_and_reparse.getClass().getName(); |
208 | | - String message = MessageUtil.format(Messages.SnapshotFactoryImpl_Error_ReparsingHeapDump, text); |
209 | | - listener.sendUserMessage(Severity.WARNING, message, ignore_and_reparse); |
210 | | - listener.subTask(message); |
211 | | - } |
212 | | - |
213 | | - if (answer == null) |
214 | | - { |
215 | | - File lockFile = new File(prefix + "lock.index"); //$NON-NLS-1$ |
216 | | - /* |
217 | | - * For autocloseable, the closeable object will be closed |
218 | | - * when parsing is done. This will release the lock and |
219 | | - * delete the lock file. |
220 | | - */ |
221 | | - try (Closeable ac = lockParse(file, lockFile, listener)) |
| 220 | + catch (IOException ignore_and_reparse) |
222 | 221 | { |
223 | | - deleteIndexFiles(file, prefix, lockFile, listener); |
224 | | - answer = parse(file, prefix, args, listtypes, listener); |
| 222 | + String text = ignore_and_reparse.getMessage() != null ? ignore_and_reparse.getMessage() |
| 223 | + : ignore_and_reparse.getClass().getName(); |
| 224 | + String message = MessageUtil.format(Messages.SnapshotFactoryImpl_Error_ReparsingHeapDump, text); |
| 225 | + listener.sendUserMessage(Severity.WARNING, message, ignore_and_reparse); |
| 226 | + listener.subTask(message); |
225 | 227 | } |
226 | | - catch (IOException e) |
| 228 | + |
| 229 | + if (answer == null) |
227 | 230 | { |
228 | | - throw new SnapshotException(e); |
| 231 | + File lockFile = new File(prefix + "lock.index"); //$NON-NLS-1$ |
| 232 | + /* |
| 233 | + * For autocloseable, the closeable object will be closed when |
| 234 | + * parsing is done. This will release the lock and delete the |
| 235 | + * lock file. |
| 236 | + */ |
| 237 | + try (Closeable ac = lockParse(file, lockFile, listener)) |
| 238 | + { |
| 239 | + deleteIndexFiles(file, prefix, lockFile, listener); |
| 240 | + answer = parse(file, prefix, args, listtypes, listener); |
| 241 | + } |
| 242 | + catch (IOException e) |
| 243 | + { |
| 244 | + throw new SnapshotException(e); |
| 245 | + } |
229 | 246 | } |
230 | | - } |
231 | 247 |
|
232 | | - entry = new SnapshotEntry(1, answer); |
| 248 | + entry = new SnapshotEntry(1, answer); |
233 | 249 |
|
234 | | - snapshotCache.put(file, entry); |
| 250 | + snapshotCache.put(file, entry); |
235 | 251 |
|
236 | | - return answer; |
| 252 | + return answer; |
| 253 | + } |
| 254 | + finally |
| 255 | + { |
| 256 | + ZonedDateTime end = ZonedDateTime.now(); |
| 257 | + Duration duration = Duration.between(start, end); |
| 258 | + // ISO8601 format, e.g. PT10H30M182S |
| 259 | + String humanDuration = duration.toString().substring(2) /* |
| 260 | + * remove |
| 261 | + * leading |
| 262 | + * PT |
| 263 | + */ |
| 264 | + .replaceAll("([HMS])", "$1 ").toLowerCase().trim(); |
| 265 | + double durationSeconds = (double) duration.toMillis() / 1000D; |
| 266 | + listener.sendUserMessage(Severity.INFO, |
| 267 | + MessageUtil.format(Messages.SnapshotFactoryImpl_FinishOpeningDump, |
| 268 | + new DecimalFormat("#,###.00").format(durationSeconds), humanDuration, |
| 269 | + DateTimeFormatter.ISO_ZONED_DATE_TIME.format(end)), |
| 270 | + null); |
| 271 | + } |
237 | 272 | } |
238 | 273 |
|
239 | 274 | /** |
|
0 commit comments