src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp
changeset 50113 caf115bb98ad
child 53897 0abec72a3ac2
equal deleted inserted replaced
50112:7a2a740815b7 50113:caf115bb98ad
       
     1 /*
       
     2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
       
    27 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
       
    28 #include "jfr/writers/jfrBigEndianWriter.hpp"
       
    29 
       
    30 JfrCheckpointFlush::JfrCheckpointFlush(Type* old, size_t used, size_t requested, Thread* t) :
       
    31   _result(JfrCheckpointManager::flush(old, used, requested, t)) {}
       
    32 
       
    33 JfrCheckpointWriter::JfrCheckpointWriter(bool flushpoint, bool header, Thread* thread) :
       
    34   JfrCheckpointWriterBase(JfrCheckpointManager::lease_buffer(thread), thread),
       
    35   _time(JfrTicks::now()),
       
    36   _offset(0),
       
    37   _count(0),
       
    38   _flushpoint(flushpoint),
       
    39   _header(header) {
       
    40   assert(this->is_acquired(), "invariant");
       
    41   assert(0 == this->current_offset(), "invariant");
       
    42   if (_header) {
       
    43     reserve(sizeof(JfrCheckpointEntry));
       
    44   }
       
    45 }
       
    46 
       
    47 static void write_checkpoint_header(u1* pos, jlong size, jlong time, bool flushpoint, juint type_count) {
       
    48   assert(pos != NULL, "invariant");
       
    49   JfrBigEndianWriter be_writer(pos, sizeof(JfrCheckpointEntry));
       
    50   be_writer.write(size);
       
    51   be_writer.write(time);
       
    52   be_writer.write(JfrTicks::now().value() - time);
       
    53   be_writer.write(flushpoint ? (juint)1 : (juint)0);
       
    54   be_writer.write(type_count);
       
    55   assert(be_writer.is_valid(), "invariant");
       
    56 }
       
    57 
       
    58 JfrCheckpointWriter::~JfrCheckpointWriter() {
       
    59   assert(this->is_acquired(), "invariant");
       
    60   if (!this->is_valid() || !_header) {
       
    61     release();
       
    62     return;
       
    63   }
       
    64   if (0 == count()) {
       
    65     assert(this->used_size() == sizeof(JfrCheckpointEntry), "invariant");
       
    66     this->seek(_offset);
       
    67     release();
       
    68     return;
       
    69   }
       
    70   assert(_header, "invariant");
       
    71   assert(this->is_valid(), "invariant");
       
    72   assert(count() > 0, "invariant");
       
    73   assert(this->used_size() > sizeof(JfrCheckpointEntry), "invariant");
       
    74   const jlong size = this->current_offset();
       
    75   assert(size + this->start_pos() == this->current_pos(), "invariant");
       
    76   write_checkpoint_header(const_cast<u1*>(this->start_pos()), size, _time, is_flushpoint(), count());
       
    77   release();
       
    78 }
       
    79 
       
    80 void JfrCheckpointWriter::set_flushpoint(bool flushpoint) {
       
    81   _flushpoint = flushpoint;
       
    82 }
       
    83 
       
    84 bool JfrCheckpointWriter::is_flushpoint() const {
       
    85   return _flushpoint;
       
    86 }
       
    87 
       
    88 juint JfrCheckpointWriter::count() const {
       
    89   return _count;
       
    90 }
       
    91 
       
    92 void JfrCheckpointWriter::set_count(juint count) {
       
    93   _count = count;
       
    94 }
       
    95 
       
    96 void JfrCheckpointWriter::release() {
       
    97   assert(this->is_acquired(), "invariant");
       
    98   if (!this->is_valid() || this->used_size() == 0) {
       
    99     return;
       
   100   }
       
   101   assert(this->used_size() > 0, "invariant");
       
   102   // write through to backing storage
       
   103   this->commit();
       
   104   assert(0 == this->current_offset(), "invariant");
       
   105 }
       
   106 
       
   107 void JfrCheckpointWriter::write_type(JfrTypeId type_id) {
       
   108   assert(type_id < TYPES_END, "invariant");
       
   109   write<u8>(type_id);
       
   110   increment();
       
   111 }
       
   112 
       
   113 void JfrCheckpointWriter::write_key(u8 key) {
       
   114   write<u8>(key);
       
   115 }
       
   116 
       
   117 void JfrCheckpointWriter::increment() {
       
   118   ++_count;
       
   119 }
       
   120 
       
   121 void JfrCheckpointWriter::write_count(u4 nof_entries) {
       
   122   write<u4>((u4)nof_entries);
       
   123 }
       
   124 
       
   125 void JfrCheckpointWriter::write_count(u4 nof_entries, jlong offset) {
       
   126   write_padded_at_offset(nof_entries, offset);
       
   127 }
       
   128 
       
   129 const u1* JfrCheckpointWriter::session_data(size_t* size, const JfrCheckpointContext* ctx /* 0 */) {
       
   130   assert(this->is_acquired(), "wrong state!");
       
   131   if (!this->is_valid()) {
       
   132     *size = 0;
       
   133     return NULL;
       
   134   }
       
   135   if (ctx != NULL) {
       
   136     const u1* session_start_pos = this->start_pos() + ctx->offset;
       
   137     *size = this->current_pos() - session_start_pos;
       
   138     return session_start_pos;
       
   139   }
       
   140   *size = this->used_size();
       
   141   assert(this->start_pos() + *size == this->current_pos(), "invariant");
       
   142   write_checkpoint_header(const_cast<u1*>(this->start_pos()), this->used_offset(), _time, is_flushpoint(), count());
       
   143   this->seek(_offset + (_header ? sizeof(JfrCheckpointEntry) : 0));
       
   144   set_count(0);
       
   145   return this->start_pos();
       
   146 }
       
   147 
       
   148 const JfrCheckpointContext JfrCheckpointWriter::context() const {
       
   149   JfrCheckpointContext ctx;
       
   150   ctx.offset = this->current_offset();
       
   151   ctx.count = this->count();
       
   152   return ctx;
       
   153 }
       
   154 
       
   155 void JfrCheckpointWriter::set_context(const JfrCheckpointContext ctx) {
       
   156   this->seek(ctx.offset);
       
   157   set_count(ctx.count);
       
   158 }
       
   159 bool JfrCheckpointWriter::has_data() const {
       
   160   return this->used_size() > sizeof(JfrCheckpointEntry);
       
   161 }
       
   162 
       
   163 JfrCheckpointBlobHandle JfrCheckpointWriter::checkpoint_blob() {
       
   164   size_t size = 0;
       
   165   const u1* data = session_data(&size);
       
   166   return JfrCheckpointBlob::make(data, size);
       
   167 }
       
   168 
       
   169 JfrCheckpointBlobHandle JfrCheckpointWriter::copy(const JfrCheckpointContext* ctx /* 0 */) {
       
   170   if (ctx == NULL) {
       
   171     return checkpoint_blob();
       
   172   }
       
   173   size_t size = 0;
       
   174   const u1* data = session_data(&size, ctx);
       
   175   return JfrCheckpointBlob::make(data, size);
       
   176 }
       
   177 
       
   178 JfrCheckpointBlobHandle JfrCheckpointWriter::move(const JfrCheckpointContext* ctx /* 0 */) {
       
   179   JfrCheckpointBlobHandle data = copy(ctx);
       
   180   if (ctx != NULL) {
       
   181     const_cast<JfrCheckpointContext*>(ctx)->count = 0;
       
   182     set_context(*ctx);
       
   183   }
       
   184   return data;
       
   185 }