1#ifndef CASACORE_ROW_BASED_FILE_H_
2#define CASACORE_ROW_BASED_FILE_H_
29 rhs.need_truncate_ =
false;
41 file_ = open(filename.c_str(), O_CREAT | O_RDWR | O_TRUNC,
42 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
44 throw std::runtime_error(
"I/O error: could not create new file '" +
55 file_ = open(filename.c_str(), O_RDWR);
57 file_ = open(filename.c_str(), O_RDONLY);
59 throw std::runtime_error(
"I/O error: could not open file '" + filename +
63 ReadData(
reinterpret_cast<unsigned char*
>(&magic_tag),
sizeof(uint32_t));
65 throw std::runtime_error(
66 "Could not read file " + filename +
67 ": file does not obey the Casacore row-based file format: either the "
68 "file is damaged, or this is not a Casacore row-based file");
71 uint32_t file_version;
72 ReadData(
reinterpret_cast<unsigned char*
>(&file_version),
sizeof(uint32_t));
73 const uint32_t major_version = (file_version & 0xFF00) >> 8;
74 constexpr uint32_t kWriterMajorVersion = (
kFileVersion & 0xFF00) >> 8;
75 if (major_version > kWriterMajorVersion) {
76 throw std::runtime_error(
"The file " + filename +
77 " requires a reader of at least major version " +
78 std::to_string(major_version) +
79 ". This reader is for major version " +
80 std::to_string(kWriterMajorVersion) +
".");
85 std::array<
unsigned char,
sizeof(uint32_t) + 2 *
sizeof(uint64_t)>
86 rest_of_private_header;
87 ReadData(rest_of_private_header.data(), rest_of_private_header.size());
89 reinterpret_cast<uint32_t&
>(rest_of_private_header.data()[0]);
90 stride_ =
reinterpret_cast<uint64_t&
>(
91 rest_of_private_header.data()[
sizeof(uint32_t)]);
92 size_t file_user_header_size =
reinterpret_cast<uint64_t&
>(
93 rest_of_private_header.data()[
sizeof(uint32_t) +
sizeof(uint64_t)]);
94 if (file_user_header_size != header_size) {
95 throw std::runtime_error(
"Error reading file " + filename +
96 ": inconsistent size of private header");
100 const uint64_t pos = lseek(
file_, 0, SEEK_END);
111 std::swap(
file_, rhs.file_);
113 std::swap(
n_rows_, rhs.n_rows_);
115 std::swap(
stride_, rhs.stride_);
146 throw std::runtime_error(
147 "I/O error: could not truncate file '" +
filename_ +
"' to have " +
148 std::to_string(n_rows) +
" rows: " +
ErrorString());
152 void Seek(off_t pos,
int seek_direction) {
153 const off_t result = lseek(
file_, pos, seek_direction);
155 throw std::runtime_error(
"I/O error: could not seek through file '" +
159 void ReadData(
unsigned char* data, uint64_t size) {
160 const int result = ::read(
file_, data, size);
162 throw std::runtime_error(
"I/O error: could not read from file '" +
166 void WriteData(
const unsigned char* data, uint64_t size) {
167 const int result = write(
file_, data, size);
169 throw std::runtime_error(
"I/O error: could not write to file '" +
253 throw std::runtime_error(
"Could not close file " +
filename_);
258 std::array<unsigned char, kWriterPrivateHeaderSize> private_header_buffer;
259 reinterpret_cast<uint32_t&
>(private_header_buffer[0]) =
kMagicFileTag;
260 reinterpret_cast<uint32_t&
>(private_header_buffer[4]) =
kFileVersion;
261 reinterpret_cast<uint32_t&
>(private_header_buffer[8]) =
263 reinterpret_cast<uint64_t&
>(private_header_buffer[12]) =
stride_;
264 reinterpret_cast<uint64_t&
>(private_header_buffer[20]) =
HeaderSize();
266 WriteData(private_header_buffer.data(), private_header_buffer.size());
282 3 *
sizeof(uint32_t) + 2 *
sizeof(uint64_t);
308 if (result_value == 0)
311 return "Unknown error";
316 return std::string(returned_buffer);
void WriteData(const unsigned char *data, uint64_t size)
static constexpr uint32_t kFileVersion
Version of this file, in format 0xaabb, where aa is the major version and bb is the minor version.
uint64_t data_location_
This variable is also used to set/calculate the header size, using the relation: data_location_ = pri...
static constexpr uint32_t kWriterPrivateHeaderSize
The size of the private header that the writer creates for the current file format.
RowBasedFile(RowBasedFile &&rhs) noexcept
void Seek(off_t pos, int seek_direction)
static std::string ErrorStringHelper(char *returned_buffer, char *)
uint64_t DataLocation() const
Offset of the first row in the file.
void SetStride(uint64_t new_stride)
Set the number of bytes per row for this file.
void ReadHeader(unsigned char *data)
Read an optional extra header to the file.
RowBasedFile(const std::string &filename, size_t header_size)
Open an existing columnar file.
const std::string & Filename() const
uint32_t private_header_size_
RowBasedFile & operator=(RowBasedFile &&rhs)
static constexpr uint32_t kMagicFileTag
First four bytes of a file.
void WriteHeader(const unsigned char *data)
Write an optional extra header to the file.
void AddRows(uint64_t n_rows)
Adds a given number of rows to the back of the file.
void Truncate(uint64_t n_rows)
int file_
The "C" file API is used because we need to use (f)truncate, which is not available from the C++ fstr...
uint64_t HeaderSize() const
Number of bytes reserved for an optional header.
uint64_t NRows() const
Total number of rows stored in this file.
void CloseWithoutTruncate()
RowBasedFile(const RowBasedFile &rhs)=delete
void ReadData(unsigned char *data, uint64_t size)
void DeleteRow()
Deletes the last row.
static std::string ErrorStringHelper(int result_value, char *buffer)
static std::string ErrorString()
uint64_t Stride() const
Total number of bytes in one row.
void SetNRows(uint64_t new_n_rows)
void Close()
Close the file.
void WritePrivateHeader()
this file contains all the compiler specific defines
void close() override
Flush and close the file.