46 |
46 |
47 public final class RepositoryFiles { |
47 public final class RepositoryFiles { |
48 private final FileAccess fileAccess; |
48 private final FileAccess fileAccess; |
49 private final NavigableMap<Long, Path> pathSet = new TreeMap<>(); |
49 private final NavigableMap<Long, Path> pathSet = new TreeMap<>(); |
50 private final Map<Path, Long> pathLookup = new HashMap<>(); |
50 private final Map<Path, Long> pathLookup = new HashMap<>(); |
|
51 private final Path repository; |
51 private volatile boolean closed; |
52 private volatile boolean closed; |
52 private Path repository; |
|
53 |
53 |
54 public RepositoryFiles(FileAccess fileAccess, Path repository) { |
54 public RepositoryFiles(FileAccess fileAccess, Path repository) { |
55 this.repository = repository; |
55 this.repository = repository; |
56 this.fileAccess = fileAccess; |
56 this.fileAccess = fileAccess; |
57 } |
57 } |
127 // ignore |
127 // ignore |
128 } |
128 } |
129 } |
129 } |
130 |
130 |
131 private boolean updatePaths() throws IOException { |
131 private boolean updatePaths() throws IOException { |
132 if (repository == null) { |
132 boolean foundNew = false; |
133 SafePath p = Repository.getRepository().getRepositoryPath(); |
133 Path repoPath = repository; |
134 if (p == null) { |
134 if (repoPath == null) { |
135 return false; |
135 // Always get the latest repository if 'jcmd JFR.configure |
|
136 // repositorypath=...' has been executed |
|
137 SafePath sf = Repository.getRepository().getRepositoryPath(); |
|
138 if (sf == null) { |
|
139 return false; // not initialized |
136 } |
140 } |
137 repository = p.toPath(); |
141 repoPath = sf.toPath(); |
138 } |
142 } |
139 boolean foundNew = false; |
143 |
140 List<Path> added = new ArrayList<>(); |
144 try (DirectoryStream<Path> dirStream = fileAccess.newDirectoryStream(repoPath)) { |
141 Set<Path> current = new HashSet<>(); |
145 List<Path> added = new ArrayList<>(); |
142 try (DirectoryStream<Path> dirStream = fileAccess.newDirectoryStream(repository)) { |
146 Set<Path> current = new HashSet<>(); |
143 for (Path p : dirStream) { |
147 for (Path p : dirStream) { |
144 if (!pathLookup.containsKey(p)) { |
148 if (!pathLookup.containsKey(p)) { |
145 String s = p.toString(); |
149 String s = p.toString(); |
146 if (s.endsWith(".jfr")) { |
150 if (s.endsWith(".jfr")) { |
147 added.add(p); |
151 added.add(p); |
148 Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.DEBUG, "New file found: " + p.toAbsolutePath()); |
152 Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.DEBUG, "New file found: " + p.toAbsolutePath()); |
149 } |
153 } |
150 current.add(p); |
154 current.add(p); |
151 } |
155 } |
152 } |
156 } |
|
157 List<Path> removed = new ArrayList<>(); |
|
158 for (Path p : pathLookup.keySet()) { |
|
159 if (!current.contains(p)) { |
|
160 removed.add(p); |
|
161 } |
|
162 } |
|
163 |
|
164 for (Path remove : removed) { |
|
165 Long time = pathLookup.get(remove); |
|
166 pathSet.remove(time); |
|
167 pathLookup.remove(remove); |
|
168 } |
|
169 Collections.sort(added, (p1, p2) -> p1.compareTo(p2)); |
|
170 for (Path p : added) { |
|
171 // Only add files that have a complete header |
|
172 // as the JVM may be in progress writing the file |
|
173 long size = fileAccess.fileSize(p); |
|
174 if (size >= ChunkHeader.HEADER_SIZE) { |
|
175 long startNanos = readStartTime(p); |
|
176 pathSet.put(startNanos, p); |
|
177 pathLookup.put(p, startNanos); |
|
178 foundNew = true; |
|
179 } |
|
180 } |
|
181 return foundNew; |
153 } |
182 } |
154 List<Path> removed = new ArrayList<>(); |
|
155 for (Path p : pathLookup.keySet()) { |
|
156 if (!current.contains(p)) { |
|
157 removed.add(p); |
|
158 } |
|
159 } |
|
160 |
|
161 for (Path remove : removed) { |
|
162 Long time = pathLookup.get(remove); |
|
163 pathSet.remove(time); |
|
164 pathLookup.remove(remove); |
|
165 } |
|
166 Collections.sort(added, (p1, p2) -> p1.compareTo(p2)); |
|
167 for (Path p : added) { |
|
168 // Only add files that have a complete header |
|
169 // as the JVM may be in progress writing the file |
|
170 long size = fileAccess.fileSize(p); |
|
171 if (size >= ChunkHeader.HEADER_SIZE) { |
|
172 long startNanos = readStartTime(p); |
|
173 pathSet.put(startNanos, p); |
|
174 pathLookup.put(p, startNanos); |
|
175 foundNew = true; |
|
176 } |
|
177 } |
|
178 return foundNew; |
|
179 } |
183 } |
180 |
184 |
181 private long readStartTime(Path p) throws IOException { |
185 private long readStartTime(Path p) throws IOException { |
182 try (RecordingInput in = new RecordingInput(p.toFile(), fileAccess, 100)) { |
186 try (RecordingInput in = new RecordingInput(p.toFile(), fileAccess, 100)) { |
183 ChunkHeader c = new ChunkHeader(in); |
187 ChunkHeader c = new ChunkHeader(in); |