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 '" +
162 throw std::runtime_error(
"I/O error: could not read from file '" +
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);
RowBasedFile(const std::string &filename, uint64_t header_size, uint64_t stride)
Create or overwrite a new columnar file on disk.
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
virtual int read()
The read()' and write()' functions control reading and writing data from the external FITS I/O medium...
void close() override
Flush and close the file.
virtual int write(FitsOutput &)