8217647: JFR: recordings on 32-bit systems unreadable

Co-authored-by: Markus Gronlund <markus.gronlund@oracle.com>
Reviewed-by: egahlin
This commit is contained in:
Boris Ulasevich 2019-02-22 17:30:07 +03:00
parent 2c2ca43c15
commit 504562b3a4
21 changed files with 107 additions and 103 deletions

View File

@ -114,7 +114,7 @@ NO_TRANSITION(void, jfr_set_enabled(JNIEnv* env, jobject jvm, jlong event_type_i
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_file_notification(JNIEnv* env, jobject jvm, jlong threshold))
JfrChunkRotation::set_threshold((intptr_t)threshold);
JfrChunkRotation::set_threshold(threshold);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_sample_threads(JNIEnv* env, jobject jvm, jboolean sampleThreads))

View File

@ -44,13 +44,13 @@ JfrCheckpointWriter::JfrCheckpointWriter(bool flushpoint, bool header, Thread* t
}
}
static void write_checkpoint_header(u1* pos, jlong size, jlong time, bool flushpoint, juint type_count) {
static void write_checkpoint_header(u1* pos, int64_t size, jlong time, bool flushpoint, u4 type_count) {
assert(pos != NULL, "invariant");
JfrBigEndianWriter be_writer(pos, sizeof(JfrCheckpointEntry));
be_writer.write(size);
be_writer.write(time);
be_writer.write(JfrTicks::now().value() - time);
be_writer.write(flushpoint ? (juint)1 : (juint)0);
be_writer.write(flushpoint ? (u4)1 : (u4)0);
be_writer.write(type_count);
assert(be_writer.is_valid(), "invariant");
}
@ -71,7 +71,7 @@ JfrCheckpointWriter::~JfrCheckpointWriter() {
assert(this->is_valid(), "invariant");
assert(count() > 0, "invariant");
assert(this->used_size() > sizeof(JfrCheckpointEntry), "invariant");
const jlong size = this->current_offset();
const int64_t size = this->current_offset();
assert(size + this->start_pos() == this->current_pos(), "invariant");
write_checkpoint_header(const_cast<u1*>(this->start_pos()), size, _time, is_flushpoint(), count());
release();
@ -85,11 +85,11 @@ bool JfrCheckpointWriter::is_flushpoint() const {
return _flushpoint;
}
juint JfrCheckpointWriter::count() const {
u4 JfrCheckpointWriter::count() const {
return _count;
}
void JfrCheckpointWriter::set_count(juint count) {
void JfrCheckpointWriter::set_count(u4 count) {
_count = count;
}
@ -111,7 +111,7 @@ void JfrCheckpointWriter::write_type(JfrTypeId type_id) {
}
void JfrCheckpointWriter::write_key(u8 key) {
write<u8>(key);
write(key);
}
void JfrCheckpointWriter::increment() {
@ -119,10 +119,10 @@ void JfrCheckpointWriter::increment() {
}
void JfrCheckpointWriter::write_count(u4 nof_entries) {
write<u4>((u4)nof_entries);
write(nof_entries);
}
void JfrCheckpointWriter::write_count(u4 nof_entries, jlong offset) {
void JfrCheckpointWriter::write_count(u4 nof_entries, int64_t offset) {
write_padded_at_offset(nof_entries, offset);
}

View File

@ -49,21 +49,21 @@ typedef AcquireReleaseMemoryWriterHost<JfrCheckpointAdapter, StackObj > JfrTrans
typedef EventWriterHost<BigEndianEncoder, CompressedIntegerEncoder, JfrTransactionalCheckpointWriter> JfrCheckpointWriterBase;
struct JfrCheckpointContext {
jlong offset;
juint count;
int64_t offset;
u4 count;
};
class JfrCheckpointWriter : public JfrCheckpointWriterBase {
friend class JfrSerializerRegistration;
private:
JfrTicks _time;
jlong _offset;
juint _count;
int64_t _offset;
u4 _count;
bool _flushpoint;
bool _header;
juint count() const;
void set_count(juint count);
u4 count() const;
void set_count(u4 count);
void increment();
void set_flushpoint(bool flushpoint);
bool is_flushpoint() const;
@ -75,7 +75,7 @@ class JfrCheckpointWriter : public JfrCheckpointWriterBase {
~JfrCheckpointWriter();
void write_type(JfrTypeId type_id);
void write_count(u4 nof_entries);
void write_count(u4 nof_entries, jlong offset);
void write_count(u4 nof_entries, int64_t offset);
void write_key(u8 key);
const JfrCheckpointContext context() const;
void set_context(const JfrCheckpointContext ctx);

View File

@ -65,7 +65,7 @@ class JfrCheckpointThreadClosure : public ThreadClosure {
private:
JfrCheckpointWriter& _writer;
JfrCheckpointContext _ctx;
const intptr_t _count_position;
const int64_t _count_position;
Thread* const _curthread;
u4 _count;

View File

@ -35,7 +35,7 @@ class JfrArtifactWriterHost : public StackObj {
WriterImpl _impl;
JfrCheckpointWriter* _writer;
JfrCheckpointContext _ctx;
jlong _count_offset;
int64_t _count_offset;
int _count;
bool _skip_header;
public:

View File

@ -29,7 +29,7 @@
#include "runtime/handles.inline.hpp"
static jobject chunk_monitor = NULL;
static intptr_t threshold = 0;
static int64_t threshold = 0;
static bool rotate = false;
static jobject install_chunk_monitor(Thread* thread) {
@ -62,7 +62,6 @@ void JfrChunkRotation::evaluate(const JfrChunkWriter& writer) {
// already in progress
return;
}
assert(!rotate, "invariant");
if (writer.size_written() > threshold) {
rotate = true;
notify();
@ -77,6 +76,6 @@ void JfrChunkRotation::on_rotation() {
rotate = false;
}
void JfrChunkRotation::set_threshold(intptr_t bytes) {
void JfrChunkRotation::set_threshold(int64_t bytes) {
threshold = bytes;
}

View File

@ -36,7 +36,7 @@ class JfrChunkWriter;
class JfrChunkRotation : AllStatic {
public:
static void evaluate(const JfrChunkWriter& writer);
static void set_threshold(intptr_t bytes);
static void set_threshold(int64_t bytes);
static bool should_rotate();
static void on_rotation();
};

View File

@ -53,19 +53,19 @@ void JfrChunkState::reset() {
set_previous_checkpoint_offset(0);
}
void JfrChunkState::set_previous_checkpoint_offset(jlong offset) {
void JfrChunkState::set_previous_checkpoint_offset(int64_t offset) {
_previous_checkpoint_offset = offset;
}
jlong JfrChunkState::previous_checkpoint_offset() const {
int64_t JfrChunkState::previous_checkpoint_offset() const {
return _previous_checkpoint_offset;
}
jlong JfrChunkState::previous_start_ticks() const {
int64_t JfrChunkState::previous_start_ticks() const {
return _previous_start_ticks;
}
jlong JfrChunkState::previous_start_nanos() const {
int64_t JfrChunkState::previous_start_nanos() const {
return _previous_start_nanos;
}
@ -92,7 +92,7 @@ void JfrChunkState::update_time_to_now() {
save_current_and_update_start_ticks();
}
jlong JfrChunkState::last_chunk_duration() const {
int64_t JfrChunkState::last_chunk_duration() const {
return _start_nanos - _previous_start_nanos;
}

View File

@ -25,7 +25,6 @@
#ifndef SHARE_JFR_RECORDER_REPOSITORY_JFRCHUNKSTATE_HPP
#define SHARE_JFR_RECORDER_REPOSITORY_JFRCHUNKSTATE_HPP
#include "jni.h"
#include "jfr/utilities/jfrAllocation.hpp"
#include "jfr/utilities/jfrTypes.hpp"
@ -33,11 +32,11 @@ class JfrChunkState : public JfrCHeapObj {
friend class JfrChunkWriter;
private:
char* _path;
jlong _start_ticks;
jlong _start_nanos;
jlong _previous_start_ticks;
jlong _previous_start_nanos;
jlong _previous_checkpoint_offset;
int64_t _start_ticks;
int64_t _start_nanos;
int64_t _previous_start_ticks;
int64_t _previous_start_nanos;
int64_t _previous_checkpoint_offset;
void update_start_ticks();
void update_start_nanos();
@ -47,11 +46,11 @@ class JfrChunkState : public JfrCHeapObj {
JfrChunkState();
~JfrChunkState();
void reset();
jlong previous_checkpoint_offset() const;
void set_previous_checkpoint_offset(jlong offset);
jlong previous_start_ticks() const;
jlong previous_start_nanos() const;
jlong last_chunk_duration() const;
int64_t previous_checkpoint_offset() const;
void set_previous_checkpoint_offset(int64_t offset);
int64_t previous_start_ticks() const;
int64_t previous_start_nanos() const;
int64_t last_chunk_duration() const;
void update_time_to_now();
void set_path(const char* path);
const char* path() const;

View File

@ -32,9 +32,8 @@
#include "runtime/os.hpp"
#include "runtime/os.inline.hpp"
const u2 JFR_VERSION_MAJOR = 2;
const u2 JFR_VERSION_MINOR = 0;
static const u2 JFR_VERSION_MAJOR = 2;
static const u2 JFR_VERSION_MINOR = 0;
static const size_t MAGIC_LEN = 4;
static const size_t FILEHEADER_SLOT_SIZE = 8;
static const size_t CHUNK_SIZE_OFFSET = 8;
@ -79,14 +78,14 @@ bool JfrChunkWriter::open() {
return is_open;
}
size_t JfrChunkWriter::close(intptr_t metadata_offset) {
size_t JfrChunkWriter::close(int64_t metadata_offset) {
write_header(metadata_offset);
this->flush();
this->close_fd();
return size_written();
return (size_t)size_written();
}
void JfrChunkWriter::write_header(intptr_t metadata_offset) {
void JfrChunkWriter::write_header(int64_t metadata_offset) {
assert(this->is_valid(), "invariant");
// Chunk size
this->write_be_at_offset(size_written(), CHUNK_SIZE_OFFSET);
@ -106,15 +105,15 @@ void JfrChunkWriter::set_chunk_path(const char* chunk_path) {
_chunkstate->set_path(chunk_path);
}
intptr_t JfrChunkWriter::size_written() const {
int64_t JfrChunkWriter::size_written() const {
return this->is_valid() ? this->current_offset() : 0;
}
intptr_t JfrChunkWriter::previous_checkpoint_offset() const {
int64_t JfrChunkWriter::previous_checkpoint_offset() const {
return _chunkstate->previous_checkpoint_offset();
}
void JfrChunkWriter::set_previous_checkpoint_offset(intptr_t offset) {
void JfrChunkWriter::set_previous_checkpoint_offset(int64_t offset) {
_chunkstate->set_previous_checkpoint_offset(offset);
}

View File

@ -41,16 +41,16 @@ class JfrChunkWriter : public JfrChunkWriterBase {
JfrChunkState* _chunkstate;
bool open();
size_t close(intptr_t metadata_offset);
void write_header(intptr_t metadata_offset);
size_t close(int64_t metadata_offset);
void write_header(int64_t metadata_offset);
void set_chunk_path(const char* chunk_path);
public:
JfrChunkWriter();
bool initialize();
intptr_t size_written() const;
intptr_t previous_checkpoint_offset() const;
void set_previous_checkpoint_offset(intptr_t offset);
int64_t size_written() const;
int64_t previous_checkpoint_offset() const;
void set_previous_checkpoint_offset(int64_t offset);
void time_stamp_chunk_now();
};

View File

@ -147,10 +147,10 @@ static void date_time(char* buffer, size_t buffer_len) {
iso8601_to_date_time(buffer);
}
static jlong file_size(fio_fd fd) {
static int64_t file_size(fio_fd fd) {
assert(fd != invalid_fd, "invariant");
const jlong current_offset = os::current_file_offset(fd);
const jlong size = os::lseek(fd, 0, SEEK_END);
const int64_t current_offset = os::current_file_offset(fd);
const int64_t size = os::lseek(fd, 0, SEEK_END);
os::seek_to_file_offset(fd, current_offset);
return size;
}
@ -218,7 +218,7 @@ const char* const RepositoryIterator::filter(const char* entry) const {
if (invalid_fd == entry_fd) {
return NULL;
}
const jlong entry_size = file_size(entry_fd);
const int64_t entry_size = file_size(entry_fd);
os::close(entry_fd);
if (0 == entry_size) {
return NULL;
@ -260,6 +260,7 @@ void RepositoryIterator::print_repository_files() const {
}
}
#endif
bool RepositoryIterator::has_next() const {
return (_files != NULL && _iterator < _files->length());
}
@ -275,21 +276,27 @@ static void write_emergency_file(fio_fd emergency_fd, const RepositoryIterator&
if (file_copy_block == NULL) {
return;
}
jlong bytes_written_total = 0;
int64_t bytes_written_total = 0;
while (iterator.has_next()) {
fio_fd current_fd = invalid_fd;
const char* const fqn = iterator.next();
if (fqn != NULL) {
current_fd = open_existing(fqn);
if (current_fd != invalid_fd) {
const jlong current_filesize = file_size(current_fd);
const int64_t current_filesize = file_size(current_fd);
assert(current_filesize > 0, "invariant");
jlong bytes_read = 0;
jlong bytes_written = 0;
int64_t bytes_read = 0;
int64_t bytes_written = 0;
while (bytes_read < current_filesize) {
bytes_read += (jlong)os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
assert(bytes_read - bytes_written <= (jlong)size_of_file_copy_block, "invariant");
bytes_written += (jlong)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
if (-1 == read_result) {
log_info(jfr) ( // For user, should not be "jfr, system"
"Unable to recover JFR data");
break;
}
bytes_read += (int64_t)read_result;
assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
assert(bytes_read == bytes_written, "invariant");
}
os::close(current_fd);
@ -468,6 +475,6 @@ bool JfrRepository::open_chunk(bool vm_error /* false */) {
return _chunkwriter->open();
}
size_t JfrRepository::close_chunk(jlong metadata_offset) {
size_t JfrRepository::close_chunk(int64_t metadata_offset) {
return _chunkwriter->close(metadata_offset);
}

View File

@ -55,7 +55,7 @@ class JfrRepository : public JfrCHeapObj {
bool set_path(const char* path);
void set_chunk_path(const char* path);
bool open_chunk(bool vm_error = false);
size_t close_chunk(jlong metadata_offset);
size_t close_chunk(int64_t metadata_offset);
void on_vm_error();
static void notify_on_new_chunk_path();
static JfrChunkWriter& chunkwriter();

View File

@ -130,18 +130,18 @@ class RotationLock : public StackObj {
bool not_acquired() const { return !_acquired; }
};
static intptr_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) {
const intptr_t prev_cp_offset = cw.previous_checkpoint_offset();
const intptr_t prev_cp_relative_offset = 0 == prev_cp_offset ? 0 : prev_cp_offset - cw.current_offset();
static int64_t write_checkpoint_event_prologue(JfrChunkWriter& cw, u8 type_id) {
const int64_t prev_cp_offset = cw.previous_checkpoint_offset();
const int64_t prev_cp_relative_offset = 0 == prev_cp_offset ? 0 : prev_cp_offset - cw.current_offset();
cw.reserve(sizeof(u4));
cw.write<u8>(EVENT_CHECKPOINT);
cw.write(JfrTicks::now());
cw.write<jlong>((jlong)0);
cw.write((int64_t)0);
cw.write(prev_cp_relative_offset); // write previous checkpoint offset delta
cw.write<bool>(false); // flushpoint
cw.write<u4>((u4)1); // nof types in this checkpoint
cw.write<u8>(type_id);
const intptr_t number_of_elements_offset = cw.current_offset();
cw.write((u4)1); // nof types in this checkpoint
cw.write(type_id);
const int64_t number_of_elements_offset = cw.current_offset();
cw.reserve(sizeof(u4));
return number_of_elements_offset;
}
@ -161,8 +161,8 @@ class WriteCheckpointEvent : public StackObj {
}
bool process() {
// current_cp_offset is also offset for the event size header field
const intptr_t current_cp_offset = _cw.current_offset();
const intptr_t num_elements_offset = write_checkpoint_event_prologue(_cw, _type_id);
const int64_t current_cp_offset = _cw.current_offset();
const int64_t num_elements_offset = write_checkpoint_event_prologue(_cw, _type_id);
// invocation
_content_functor.process();
const u4 number_of_elements = (u4)_content_functor.processed();
@ -468,9 +468,9 @@ void JfrRecorderService::safepoint_write() {
JfrMetadataEvent::lock();
}
static jlong write_metadata_event(JfrChunkWriter& chunkwriter) {
static int64_t write_metadata_event(JfrChunkWriter& chunkwriter) {
assert(chunkwriter.is_valid(), "invariant");
const jlong metadata_offset = chunkwriter.current_offset();
const int64_t metadata_offset = chunkwriter.current_offset();
JfrMetadataEvent::write(chunkwriter, metadata_offset);
return metadata_offset;
}

View File

@ -49,7 +49,7 @@ template <typename BE, typename IE, typename WriterPolicyImpl>
inline intptr_t EventWriterHost<BE, IE, WriterPolicyImpl>::end_write(void) {
assert(this->is_acquired(),
"state corruption, calling end with writer with non-acquired state!");
return this->is_valid() ? this->used_offset() : 0;
return this->is_valid() ? (intptr_t)this->used_offset() : 0;
}
template <typename BE, typename IE, typename WriterPolicyImpl>

View File

@ -48,8 +48,8 @@ class Position : public AP {
public:
size_t available_size() const;
intptr_t used_offset() const;
intptr_t current_offset() const;
int64_t used_offset() const;
int64_t current_offset() const;
size_t used_size() const;
void reset();
};

View File

@ -80,12 +80,12 @@ inline size_t Position<AP>::available_size() const {
}
template <typename AP>
inline intptr_t Position<AP>::used_offset() const {
inline int64_t Position<AP>::used_offset() const {
return _current_pos - _start_pos;
}
template <typename AP>
inline intptr_t Position<AP>::current_offset() const {
inline int64_t Position<AP>::current_offset() const {
return this->used_offset();
}

View File

@ -33,9 +33,9 @@ class StreamWriterHost : public MemoryWriterHost<Adapter, AP> {
public:
typedef typename Adapter::StorageType StorageType;
private:
intptr_t _stream_pos;
int64_t _stream_pos;
fio_fd _fd;
intptr_t current_stream_position() const;
int64_t current_stream_position() const;
protected:
StreamWriterHost(StorageType* storage, Thread* thread);
@ -47,8 +47,8 @@ class StreamWriterHost : public MemoryWriterHost<Adapter, AP> {
bool has_valid_fd() const;
public:
intptr_t current_offset() const;
void seek(intptr_t offset);
int64_t current_offset() const;
void seek(int64_t offset);
void flush();
void write_unbuffered(const void* src, size_t len);
bool is_valid() const;

View File

@ -44,7 +44,7 @@ StreamWriterHost<Adapter, AP>::StreamWriterHost(Thread* thread) :
}
template <typename Adapter, typename AP>
inline intptr_t StreamWriterHost<Adapter, AP>::current_stream_position() const {
inline int64_t StreamWriterHost<Adapter, AP>::current_stream_position() const {
return this->used_offset() + _stream_pos;
}
@ -73,7 +73,7 @@ template <typename Adapter, typename AP>
inline void StreamWriterHost<Adapter, AP>::flush(size_t size) {
assert(size > 0, "invariant");
assert(this->is_valid(), "invariant");
_stream_pos += os::write(_fd, this->start_pos(), (int)size);
_stream_pos += os::write(_fd, this->start_pos(), (unsigned int)size);
StorageHost<Adapter, AP>::reset();
assert(0 == this->used_offset(), "invariant");
}
@ -84,12 +84,12 @@ inline bool StreamWriterHost<Adapter, AP>::has_valid_fd() const {
}
template <typename Adapter, typename AP>
inline intptr_t StreamWriterHost<Adapter, AP>::current_offset() const {
inline int64_t StreamWriterHost<Adapter, AP>::current_offset() const {
return current_stream_position();
}
template <typename Adapter, typename AP>
void StreamWriterHost<Adapter, AP>::seek(intptr_t offset) {
void StreamWriterHost<Adapter, AP>::seek(int64_t offset) {
this->flush();
assert(0 == this->used_offset(), "can only seek from beginning");
_stream_pos = os::seek_to_file_offset(_fd, offset);
@ -110,7 +110,7 @@ void StreamWriterHost<Adapter, AP>::write_unbuffered(const void* buf, size_t len
this->flush();
assert(0 == this->used_offset(), "can only seek from beginning");
while (len > 0) {
const int n = MIN2<int>((int)len, INT_MAX);
const unsigned int n = MIN2((unsigned int)len, (unsigned int)INT_MAX);
_stream_pos += os::write(_fd, buf, n);
len -= n;
}

View File

@ -91,12 +91,12 @@ class WriterHost : public WriterPolicyImpl {
void bytes(const void* buf, size_t len);
void write_utf8_u2_len(const char* value);
template <typename T>
void write_padded_at_offset(T value, intptr_t offset);
void write_padded_at_offset(T value, int64_t offset);
template <typename T>
void write_at_offset(T value, intptr_t offset);
void write_at_offset(T value, int64_t offset);
template <typename T>
void write_be_at_offset(T value, intptr_t offset);
intptr_t reserve(size_t size);
void write_be_at_offset(T value, int64_t offset);
int64_t reserve(size_t size);
};
#endif // SHARE_JFR_WRITERS_JFRWRITERHOST_HPP

View File

@ -196,7 +196,7 @@ inline void WriterHost<BE, IE, WriterPolicyImpl>::write(float value) {
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(double value) {
be_write(*(uintptr_t*)&(value));
be_write(*(u8*)&(value));
}
template <typename BE, typename IE, typename WriterPolicyImpl>
@ -317,9 +317,9 @@ inline void WriterHost<BE, IE, WriterPolicyImpl>::write_utf8_u2_len(const char*
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline intptr_t WriterHost<BE, IE, WriterPolicyImpl>::reserve(size_t size) {
inline int64_t WriterHost<BE, IE, WriterPolicyImpl>::reserve(size_t size) {
if (ensure_size(size) != NULL) {
intptr_t reserved_offset = this->current_offset();
const int64_t reserved_offset = this->current_offset();
this->set_current_pos(size);
return reserved_offset;
}
@ -329,9 +329,9 @@ inline intptr_t WriterHost<BE, IE, WriterPolicyImpl>::reserve(size_t size) {
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded_at_offset(T value, intptr_t offset) {
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
const intptr_t current = this->current_offset();
const int64_t current = this->current_offset();
this->seek(offset);
write_padded(value);
this->seek(current); // restore
@ -340,9 +340,9 @@ inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded_at_offset(T value
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_at_offset(T value, intptr_t offset) {
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
const intptr_t current = this->current_offset();
const int64_t current = this->current_offset();
this->seek(offset);
write(value);
this->seek(current); // restore
@ -351,9 +351,9 @@ inline void WriterHost<BE, IE, WriterPolicyImpl>::write_at_offset(T value, intpt
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_be_at_offset(T value, intptr_t offset) {
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_be_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
const intptr_t current = this->current_offset();
const int64_t current = this->current_offset();
this->seek(offset);
be_write(value);
this->seek(current); // restore