1#ifndef CASACORE_ROW_BASED_FILE_H_
2#define CASACORE_ROW_BASED_FILE_H_
29 rhs.need_truncate_ =
false;
38 RowBasedFile(
const std::string& filename, uint64_t header_size, uint64_t stride)
41 open(filename.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
43 throw std::runtime_error(
"I/O error: could not create new file '" + filename +
"'");
52 file_ = open(filename.c_str(), O_RDWR);
54 file_ = open(filename.c_str(), O_RDONLY);
55 if (
file_ < 0)
throw std::runtime_error(
"I/O error: could not open file '" + filename +
"'");
58 ReadData(
reinterpret_cast<unsigned char*
>(&magic_tag),
sizeof(uint32_t));
60 throw std::runtime_error(
61 "Could not read file " + filename +
62 ": file does not obey the Casacore row-based file format: either the "
63 "file is damaged, or this is not a Casacore row-based file");
66 uint32_t file_version;
67 ReadData(
reinterpret_cast<unsigned char*
>(&file_version),
sizeof(uint32_t));
68 const uint32_t major_version = (file_version & 0xFF00) >> 8;
69 constexpr uint32_t kWriterMajorVersion = (
kFileVersion & 0xFF00) >> 8;
70 if (major_version > kWriterMajorVersion) {
71 throw std::runtime_error(
72 "The file " + filename +
" requires a reader of at least major version " +
73 std::to_string(major_version) +
". This reader is for major version " +
74 std::to_string(kWriterMajorVersion) +
".");
79 std::array<
unsigned char,
sizeof(uint32_t) + 2 *
sizeof(uint64_t)> rest_of_private_header;
80 ReadData(rest_of_private_header.data(), rest_of_private_header.size());
82 stride_ =
reinterpret_cast<uint64_t&
>(rest_of_private_header.data()[
sizeof(uint32_t)]);
83 size_t file_user_header_size =
reinterpret_cast<uint64_t&
>(
84 rest_of_private_header.data()[
sizeof(uint32_t) +
sizeof(uint64_t)]);
85 if (file_user_header_size != header_size) {
86 throw std::runtime_error(
"Error reading file " + filename +
87 ": inconsistent size of private header");
91 const uint64_t pos = lseek(
file_, 0, SEEK_END);
102 std::swap(
file_, rhs.file_);
104 std::swap(
n_rows_, rhs.n_rows_);
106 std::swap(
stride_, rhs.stride_);
137 throw std::runtime_error(
"I/O error: could not truncate file '" +
filename_ +
"' to have " +
138 std::to_string(n_rows) +
" rows: " +
ErrorString());
142 void Seek(off_t pos,
int seek_direction) {
143 const off_t result = lseek(
file_, pos, seek_direction);
145 throw std::runtime_error(
"I/O error: could not seek through file '" +
filename_ +
"'");
151 throw std::runtime_error(
"I/O error: could not read from file '" +
filename_ +
"'");
157 throw std::runtime_error(
"I/O error: could not write to file '" +
filename_ +
"'");
239 if (result < 0)
throw std::runtime_error(
"Could not close file " +
filename_);
244 std::array<unsigned char, kWriterPrivateHeaderSize> private_header_buffer;
245 reinterpret_cast<uint32_t&
>(private_header_buffer[0]) =
kMagicFileTag;
246 reinterpret_cast<uint32_t&
>(private_header_buffer[4]) =
kFileVersion;
248 reinterpret_cast<uint64_t&
>(private_header_buffer[12]) =
stride_;
249 reinterpret_cast<uint64_t&
>(private_header_buffer[20]) =
HeaderSize();
251 WriteData(private_header_buffer.data(), private_header_buffer.size());
267 3 *
sizeof(uint32_t) + 2 *
sizeof(uint64_t);
293 if (result_value == 0)
296 return "Unknown error";
300 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()
For temporary backward namespace compatibility, use casa as alias for casacore.
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 &)