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(JfrTraceTime::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(JfrTraceTime::now() - 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_constant_type(JfrConstantTypeId constant_type_id) { 108 assert(constant_type_id < CONSTANT_TYPES_END, "invariant"); 109 write<u8>(constant_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_number_of_constants(u4 nof_entries) { 122 write<u4>((u4)nof_entries); 123 } 124 125 void JfrCheckpointWriter::write_number_of_constants(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 }