44 import jdk.jfr.internal.Logger; |
44 import jdk.jfr.internal.Logger; |
45 import jdk.jfr.internal.Repository; |
45 import jdk.jfr.internal.Repository; |
46 import jdk.jfr.internal.SecuritySupport.SafePath; |
46 import jdk.jfr.internal.SecuritySupport.SafePath; |
47 |
47 |
48 public final class RepositoryFiles { |
48 public final class RepositoryFiles { |
49 private final Path repository; |
49 private final FileAccess fileAccess; |
50 private final NavigableMap<Long, Path> pathSet = new TreeMap<>(); |
50 private final NavigableMap<Long, Path> pathSet = new TreeMap<>(); |
51 private final Map<Path, Long> pathLookup = new HashMap<>(); |
51 private final Map<Path, Long> pathLookup = new HashMap<>(); |
52 private volatile boolean closed; |
52 private volatile boolean closed; |
|
53 private Path repository; |
53 |
54 |
54 public RepositoryFiles(SafePath repository) { |
55 public RepositoryFiles(FileAccess fileAccess, SafePath repository) { |
55 this.repository = repository == null ? null : repository.toPath(); |
56 this.repository = repository == null ? null : repository.toPath(); |
|
57 this.fileAccess = fileAccess; |
56 } |
58 } |
57 |
59 |
58 public long getTimestamp(Path p) { |
60 public long getTimestamp(Path p) { |
59 return pathLookup.get(p); |
61 return pathLookup.get(p); |
60 } |
62 } |
61 |
63 |
62 public Path lastPath() { |
64 public Path lastPath() { |
63 // Wait for chunks |
65 // Wait for chunks |
64 while (!closed) { |
66 while (!closed) { |
65 try { |
67 try { |
66 if (updatePaths(repository)) { |
68 if (updatePaths()) { |
67 break; |
69 break; |
68 } |
70 } |
69 } catch (IOException e) { |
71 } catch (IOException e) { |
70 // ignore, not yet available |
72 // ignore, not yet available |
71 } |
73 } |
99 Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.TRACE, "Return path " + path + " for start time nanos " + timestamp); |
101 Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.TRACE, "Return path " + path + " for start time nanos " + timestamp); |
100 return path; |
102 return path; |
101 } |
103 } |
102 } |
104 } |
103 try { |
105 try { |
104 if (updatePaths(repository)) { |
106 if (updatePaths()) { |
105 continue; |
107 continue; |
106 } |
108 } |
107 } catch (IOException e) { |
109 } catch (IOException e) { |
108 Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.DEBUG, "IOException during repository file scan " + e.getMessage()); |
110 Logger.log(LogTag.JFR_SYSTEM_STREAMING, LogLevel.DEBUG, "IOException during repository file scan " + e.getMessage()); |
109 // This can happen if a chunk is being removed |
111 // This can happen if a chunk is being removed |
120 } |
122 } |
121 } |
123 } |
122 return null; |
124 return null; |
123 } |
125 } |
124 |
126 |
125 private boolean updatePaths(Path repo) throws IOException { |
127 private boolean updatePaths() throws IOException { |
126 if (repo == null) { |
128 if (repository == null) { |
127 repo = Repository.getRepository().getRepositoryPath().toPath(); |
129 SafePath p = Repository.getRepository().getRepositoryPath(); |
|
130 if (p == null) { |
|
131 return false; |
|
132 } |
|
133 repository = p.toPath(); |
128 } |
134 } |
129 boolean foundNew = false; |
135 boolean foundNew = false; |
130 List<Path> added = new ArrayList<>(); |
136 List<Path> added = new ArrayList<>(); |
131 Set<Path> current = new HashSet<>(); |
137 Set<Path> current = new HashSet<>(); |
132 try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(repo)) { |
138 try (DirectoryStream<Path> dirStream = fileAccess.newDirectoryStream(repository)) { |
133 for (Path p : dirStream) { |
139 for (Path p : dirStream) { |
134 if (!pathLookup.containsKey(p)) { |
140 if (!pathLookup.containsKey(p)) { |
135 String s = p.toString(); |
141 String s = p.toString(); |
136 if (s.endsWith(".jfr")) { |
142 if (s.endsWith(".jfr")) { |
137 added.add(p); |
143 added.add(p); |
167 } |
173 } |
168 return foundNew; |
174 return foundNew; |
169 } |
175 } |
170 |
176 |
171 private long readStartTime(Path p) throws IOException { |
177 private long readStartTime(Path p) throws IOException { |
172 try (RecordingInput in = new RecordingInput(p.toFile(), 100)) { |
178 try (RecordingInput in = new RecordingInput(p.toFile(), fileAccess, 100)) { |
173 ChunkHeader c = new ChunkHeader(in); |
179 ChunkHeader c = new ChunkHeader(in); |
174 return c.getStartNanos(); |
180 return c.getStartNanos(); |
175 } |
181 } |
176 } |
182 } |
177 |
183 |