src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp
changeset 58863 c16ac7a2eba4
parent 54623 1126f0607c70
child 59226 a0f39cc47387
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
    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);
    82   delete _instance;
    80   delete _instance;
    83   _instance = NULL;
    81   _instance = NULL;
    84 }
    82 }
    85 
    83 
    86 void JfrRepository::on_vm_error() {
    84 void JfrRepository::on_vm_error() {
    87   assert(!JfrStream_lock->owned_by_self(), "invariant");
       
    88   if (_path == NULL) {
    85   if (_path == NULL) {
    89     // completed already
    86     // completed already
    90     return;
    87     return;
    91   }
    88   }
    92   JfrEmergencyDump::on_vm_error(_path);
    89   JfrEmergencyDump::on_vm_error(_path);
   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 }