24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "jfr/jfr.hpp" |
26 #include "jfr/jfr.hpp" |
27 #include "jfr/jni/jfrJavaSupport.hpp" |
27 #include "jfr/jni/jfrJavaSupport.hpp" |
28 #include "jfr/recorder/jfrRecorder.hpp" |
28 #include "jfr/recorder/jfrRecorder.hpp" |
29 #include "jfr/recorder/repository/jfrChunkState.hpp" |
|
30 #include "jfr/recorder/repository/jfrChunkWriter.hpp" |
29 #include "jfr/recorder/repository/jfrChunkWriter.hpp" |
31 #include "jfr/recorder/repository/jfrEmergencyDump.hpp" |
30 #include "jfr/recorder/repository/jfrEmergencyDump.hpp" |
32 #include "jfr/recorder/repository/jfrRepository.hpp" |
31 #include "jfr/recorder/repository/jfrRepository.hpp" |
33 #include "jfr/recorder/service/jfrPostBox.hpp" |
32 #include "jfr/recorder/service/jfrPostBox.hpp" |
|
33 #include "logging/log.hpp" |
34 #include "memory/resourceArea.hpp" |
34 #include "memory/resourceArea.hpp" |
35 #include "runtime/mutex.hpp" |
35 #include "runtime/mutex.hpp" |
|
36 #include "runtime/os.hpp" |
36 #include "runtime/thread.inline.hpp" |
37 #include "runtime/thread.inline.hpp" |
37 |
38 |
38 static JfrRepository* _instance = NULL; |
39 static JfrRepository* _instance = NULL; |
39 |
40 |
40 JfrRepository& JfrRepository::instance() { |
41 JfrRepository& JfrRepository::instance() { |
41 return *_instance; |
42 return *_instance; |
42 } |
43 } |
43 |
44 |
44 static JfrChunkWriter* _chunkwriter = NULL; |
45 static JfrChunkWriter* _chunkwriter = NULL; |
45 |
46 |
46 static bool initialize_chunkwriter() { |
|
47 assert(_chunkwriter == NULL, "invariant"); |
|
48 _chunkwriter = new JfrChunkWriter(); |
|
49 return _chunkwriter != NULL && _chunkwriter->initialize(); |
|
50 } |
|
51 |
47 |
52 JfrChunkWriter& JfrRepository::chunkwriter() { |
48 JfrChunkWriter& JfrRepository::chunkwriter() { |
53 return *_chunkwriter; |
49 return *_chunkwriter; |
54 } |
50 } |
55 |
51 |
56 JfrRepository::JfrRepository(JfrPostBox& post_box) : _path(NULL), _post_box(post_box) {} |
52 JfrRepository::JfrRepository(JfrPostBox& post_box) : _path(NULL), _post_box(post_box) {} |
57 |
53 |
58 bool JfrRepository::initialize() { |
54 bool JfrRepository::initialize() { |
59 return initialize_chunkwriter(); |
55 assert(_chunkwriter == NULL, "invariant"); |
|
56 _chunkwriter = new JfrChunkWriter(); |
|
57 return _chunkwriter != NULL; |
60 } |
58 } |
61 |
59 |
62 JfrRepository::~JfrRepository() { |
60 JfrRepository::~JfrRepository() { |
63 if (_path != NULL) { |
61 if (_path != NULL) { |
64 JfrCHeapObj::free(_path, strlen(_path) + 1); |
62 JfrCHeapObj::free(_path, strlen(_path) + 1); |
105 } |
102 } |
106 strncpy(_path, path, path_len + 1); |
103 strncpy(_path, path, path_len + 1); |
107 return true; |
104 return true; |
108 } |
105 } |
109 |
106 |
110 void JfrRepository::set_chunk_path(const char* path) { |
107 void JfrRepository::notify_on_new_chunk_path() { |
111 assert(JfrStream_lock->owned_by_self(), "invariant"); |
108 if (Jfr::is_recording()) { |
112 chunkwriter().set_chunk_path(path); |
109 // rotations are synchronous, block until rotation completes |
|
110 instance()._post_box.post(MSG_ROTATE); |
|
111 } |
113 } |
112 } |
114 |
113 |
115 void JfrRepository::notify_on_new_chunk_path() { |
114 void JfrRepository::set_chunk_path(const char* path) { |
116 if (Jfr::is_recording()) { |
115 chunkwriter().set_path(path); |
117 instance()._post_box.post(MSG_ROTATE); |
116 } |
118 } |
117 |
|
118 jlong JfrRepository::current_chunk_start_nanos() { |
|
119 return chunkwriter().current_chunk_start_nanos(); |
119 } |
120 } |
120 |
121 |
121 /** |
122 /** |
122 * Sets the file where data should be written. |
123 * Sets the file where data should be written. |
123 * |
124 * |
132 */ |
133 */ |
133 void JfrRepository::set_chunk_path(jstring path, JavaThread* jt) { |
134 void JfrRepository::set_chunk_path(jstring path, JavaThread* jt) { |
134 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); |
135 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); |
135 ResourceMark rm(jt); |
136 ResourceMark rm(jt); |
136 const char* const canonical_chunk_path = JfrJavaSupport::c_str(path, jt); |
137 const char* const canonical_chunk_path = JfrJavaSupport::c_str(path, jt); |
137 { |
138 if (NULL == canonical_chunk_path && !_chunkwriter->is_valid()) { |
138 MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag); |
139 // new output is NULL and current output is NULL |
139 if (NULL == canonical_chunk_path && !_chunkwriter->is_valid()) { |
140 return; |
140 // new output is NULL and current output is NULL |
|
141 return; |
|
142 } |
|
143 instance().set_chunk_path(canonical_chunk_path); |
|
144 } |
141 } |
|
142 instance().set_chunk_path(canonical_chunk_path); |
145 notify_on_new_chunk_path(); |
143 notify_on_new_chunk_path(); |
146 } |
144 } |
147 |
145 |
148 void JfrRepository::set_path(jstring location, JavaThread* jt) { |
146 void JfrRepository::set_path(jstring location, JavaThread* jt) { |
149 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); |
147 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); |
153 instance().set_path(path); |
151 instance().set_path(path); |
154 } |
152 } |
155 } |
153 } |
156 |
154 |
157 bool JfrRepository::open_chunk(bool vm_error /* false */) { |
155 bool JfrRepository::open_chunk(bool vm_error /* false */) { |
158 assert(JfrStream_lock->owned_by_self(), "invariant"); |
|
159 if (vm_error) { |
156 if (vm_error) { |
160 ResourceMark rm; |
157 ResourceMark rm; |
161 _chunkwriter->set_chunk_path(JfrEmergencyDump::build_dump_path(_path)); |
158 _chunkwriter->set_path(JfrEmergencyDump::build_dump_path(_path)); |
162 } |
159 } |
163 return _chunkwriter->open(); |
160 return _chunkwriter->open(); |
164 } |
161 } |
165 |
162 |
166 size_t JfrRepository::close_chunk(int64_t metadata_offset) { |
163 size_t JfrRepository::close_chunk() { |
167 return _chunkwriter->close(metadata_offset); |
164 return _chunkwriter->close(); |
168 } |
165 } |
|
166 |
|
167 void JfrRepository::flush(JavaThread* jt) { |
|
168 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); |
|
169 if (!Jfr::is_recording()) { |
|
170 return; |
|
171 } |
|
172 if (!_chunkwriter->is_valid()) { |
|
173 return; |
|
174 } |
|
175 instance()._post_box.post(MSG_FLUSHPOINT); |
|
176 } |
|
177 |
|
178 size_t JfrRepository::flush_chunk() { |
|
179 return _chunkwriter->flush_chunk(true); |
|
180 } |