10#include <nv/index/app/forwarding_logger.h>
13# ifndef WIN32_LEAN_AND_MEAN
14# define WIN32_LEAN_AND_MEAN 1
18# include <sys/types.h>
28namespace index_common {
36 ifstream f(file_path.c_str(), ios_base::in);
53 m_open_mode =
static_cast<std::ios_base::openmode
>(0);
64 std::ios_base::openmode open_mode,
65 mi::Uint32 file_flags)
68 DWORD desired_access = 0;
69 DWORD read_write_buffer_access = 0;
71 if (open_mode & std::ios_base::in) {
72 desired_access |=
GENERIC_READ;
73 read_write_buffer_access =
PAGE_READWRITE;
75 if (open_mode & std::ios_base::out) {
76 desired_access |=
GENERIC_WRITE;
77 read_write_buffer_access =
PAGE_READWRITE;
81 DWORD share_mode =
FILE_SHARE_READ;
84 DWORD creation_disposition = 0;
87 if ( ((open_mode & std::ios_base::out)
88 || (open_mode & std::ios_base::in))
89 && !(open_mode & std::ios_base::trunc)) {
90 creation_disposition =
OPEN_ALWAYS;
92 else if ( (open_mode & std::ios_base::out)
93 && (open_mode & std::ios_base::trunc)) {
94 creation_disposition =
TRUNCATE_EXISTING;
97 DEBUG_LOG <<
"File::open(): "
98 <<
"illegal open mode 0x" << std::hex << open_mode <<
"on existing file "
104 if ( (open_mode & std::ios_base::out)
109 creation_disposition =
CREATE_NEW;
120 DWORD flags_and_attributes =
FILE_ATTRIBUTE_NORMAL;
122 flags_and_attributes |=
FILE_FLAG_SEQUENTIAL_SCAN;
131 creation_disposition,
132 flags_and_attributes,
136 DEBUG_LOG <<
"File::open(): "
137 <<
"error creating/opening file: "
142 if ( (open_mode & std::ios_base::ate)
143 || (open_mode & std::ios_base::app)) {
175 m_open_mode =
static_cast<std::ios_base::openmode
>(0);
179 virtual mi::Uint64
read(
181 mi::Uint64 start_position,
182 mi::Uint64 num_bytes_to_read)
185 DEBUG_LOG <<
"File::read(): "
186 <<
"read access on invalid file handle.";
192 Uint8* output_byte_buffer =
reinterpret_cast<Uint8*
>(output_buffer);
193 Uint64 bytes_read = 0;
197 while (bytes_read < num_bytes_to_read) {
198 static const Uint64 read_max_block_size = 512ull * 1024 * 1024;
199 const mi::Uint64 file_bytes_to_read = mi::math::clamp(num_bytes_to_read - bytes_read, 0ull, read_max_block_size);
202 DEBUG_LOG <<
"File::read(): "
203 <<
"unable to set file pointer to current position.";
207 DWORD file_bytes_read = 0;
208 if (ReadFile(
m_file_handle, output_byte_buffer + bytes_read,
static_cast<DWORD
>(file_bytes_to_read), &file_bytes_read, 0) == 0) {
209 DEBUG_LOG <<
"File::read(): "
213 if (file_bytes_read == 0) {
219 bytes_read += file_bytes_read;
226 virtual mi::Uint64
read(
228 mi::Uint64 num_bytes_to_read)
233 virtual mi::Uint64
write(
234 const void* input_buffer,
235 mi::Uint64 start_position,
236 mi::Uint64 num_bytes_to_write)
241 DEBUG_LOG <<
"File::write(): "
242 <<
"write access on invalid file handle.";
250 const Uint8* input_byte_buffer =
reinterpret_cast<const Uint8*
>(input_buffer);
251 Uint64 bytes_written = 0;
255 while (bytes_written < num_bytes_to_write) {
256 static const Uint64 write_max_block_size = 512ull * 1024 * 1024;
257 const Uint64 file_bytes_to_write = mi::math::clamp(num_bytes_to_write - bytes_written, 0ull, write_max_block_size);
263 DWORD file_bytes_written = 0;
265 input_byte_buffer + bytes_written,
266 static_cast<DWORD
>(file_bytes_to_write),
270 DEBUG_LOG <<
"File::write(): "
275 if (file_bytes_written == 0) {
280 bytes_written += file_bytes_written;
284 return bytes_written;
287 virtual mi::Uint64
write(
288 const void* input_buffer,
289 mi::Uint64 num_bytes_to_write)
297 DEBUG_LOG <<
"File::flush_buffers(): "
298 <<
"write access on invalid file handle.";
302 return FlushFileBuffers(
m_file_handle) != FALSE ? true :
false;
306 virtual mi::Uint64
size()
const
311 virtual const std::string&
file_path()
const
320 LARGE_INTEGER cur_size_li;
323 DEBUG_LOG <<
"File::actual_file_size(): "
324 <<
"error retrieving current file size: " <<
m_file_path;
328 return static_cast<mi::Uint64
>(cur_size_li.QuadPart);
331 virtual bool set_file_pointer(mi::Uint64 new_pos)
335 LARGE_INTEGER position_li;
336 position_li.QuadPart = new_pos;
338 if ( SetFilePointer(
m_file_handle, position_li.LowPart, &position_li.HighPart,
FILE_BEGIN) ==
INVALID_SET_FILE_POINTER
339 && GetLastError() !=
NO_ERROR) {
340 DEBUG_LOG <<
"File::set_file_pointer(): "
341 <<
"error setting file pointer to position "
342 << std::hex << new_pos
373 m_open_mode =
static_cast<std::ios_base::openmode
>(0);
383 std::ios_base::openmode open_mode,
384 mi::Uint32 file_flags)
388 mi::Sint32 open_flags = 0;
390 open_flags |=
O_LARGEFILE;
395 mode_t create_mode =
S_IRUSR |
S_IWUSR |
S_IRGRP |
S_IROTH;
397 if ( (open_mode & std::ios_base::in)
398 && (open_mode & std::ios_base::out)) {
399 open_flags |=
O_RDWR;
401 else if (open_mode & std::ios_base::in) {
402 open_flags |=
O_RDONLY;
404 else if (open_mode & std::ios_base::out) {
405 open_flags |=
O_WRONLY;
408 DEBUG_LOG <<
"File::open(): "
409 <<
"illegal open mode 0x" << std::hex << open_mode
415 if ( ((open_mode & std::ios_base::out)
416 || (open_mode & std::ios_base::in))
417 && !(open_mode & std::ios_base::trunc)) {
420 else if ( (open_mode & std::ios_base::out)
421 && (open_mode & std::ios_base::trunc)) {
422 open_flags |=
O_TRUNC;
425 DEBUG_LOG <<
"File::open(): "
426 <<
"illegal open mode 0x" << std::hex << open_mode <<
"on existing file "
432 if (open_mode & std::ios_base::out) {
433 open_flags |=
O_CREAT;
442 open_flags |=
O_DIRECT;
456 std::string ret_error;
458 case EACCES: ret_error.assign(
"requested access to the file is not allowed (insufficient permissions?)");
break;
459 case EEXIST: ret_error.assign(
"pathname already exists and O_CREAT and O_EXCL were used");
break;
460 case EFAULT: ret_error.assign(
"pathname points outside your accessible address space");
break;
461 case EISDIR: ret_error.assign(
"pathname refers to a directory and the access requested involved writing");
break;
462 default: ret_error.assign(
"unknown error");
break;
464 DEBUG_LOG <<
"File::open(): "
465 <<
"error opening file "
466 <<
"(" << ret_error <<
")"
472 if ( (open_mode & std::ios_base::ate)
473 || (open_mode & std::ios_base::app)) {
495 std::string ret_error;
497 case EBADF: ret_error.assign(
"invalid file descriptor");
break;
498 case EINTR: ret_error.assign(
"close interrupted by signal");
break;
499 case EIO: ret_error.assign(
"I/O error");
break;
500 default: ret_error.assign(
"unknown error");
break;
502 DEBUG_LOG <<
"File::close(): "
503 <<
"error closing file "
504 <<
"(" << ret_error <<
")"
512 m_open_mode =
static_cast<std::ios_base::openmode
>(0);
517 mi::Uint64 start_position,
518 mi::Uint64 num_bytes_to_read)
522 Uint8* output_byte_buffer =
reinterpret_cast<Uint8*
>(output_buffer);
523 Uint64 bytes_read = 0;
525 if (num_bytes_to_read <= 0) {
529 Uint64 start_pos = start_position;
531 while (bytes_read < num_bytes_to_read)
533 const Uint64 file_bytes_to_read = num_bytes_to_read - bytes_read;
534 const ssize_t file_bytes_read = ::pread(
m_file_handle, output_byte_buffer + bytes_read, file_bytes_to_read, start_pos);
536 if (file_bytes_read < 0) {
537 DEBUG_LOG <<
"File::read(): "
541 else if (file_bytes_read == 0) {
545 start_pos += file_bytes_read;
547 bytes_read += file_bytes_read;
555 mi::Uint64 start_position,
556 mi::Uint64 num_bytes_to_read)
558 const mi::Size vpage_size = 512;
566 const bool is_obuf_aligned = ((mi::Size)output_buffer % vpage_size) == 0;
567 if (!is_obuf_aligned) {
568 WARN_LOG <<
"File::read(): " <<
"output_buffer address not page-aligned (non-buffered file mode).";
571 const bool is_spos_aligned = (start_position % vpage_size) == 0;
572 if (!is_spos_aligned) {
573 WARN_LOG <<
"File::read(): " <<
"start file-position not page-aligned (non-buffered file mode).";
576 return read_plain(output_buffer, start_position, num_bytes_to_read);
579 virtual mi::Uint64
read(
void* output_buffer,
580 mi::Uint64 start_position,
581 mi::Uint64 num_bytes_to_read)
584 DEBUG_LOG <<
"File::read(): "
585 <<
"read access on invalid file handle.";
590 return read_odirect(output_buffer, start_position, num_bytes_to_read);
593 return read_plain(output_buffer, start_position, num_bytes_to_read);
599 mi::Uint64 num_bytes_to_read)
604 virtual mi::Uint64
write(
const void* input_buffer,
605 mi::Uint64 start_position,
606 mi::Uint64 num_bytes_to_write)
611 DEBUG_LOG <<
"File::write(): "
612 <<
"write access on invalid file handle.";
620 const Uint8* input_byte_buffer =
reinterpret_cast<const Uint8*
>(input_buffer);
621 Uint64 bytes_written = 0;
625 while (bytes_written < num_bytes_to_write)
627 const Uint64 file_bytes_to_write = num_bytes_to_write - bytes_written;
628 const ssize_t file_bytes_written = ::pwrite(
m_file_handle, input_byte_buffer + bytes_written, file_bytes_to_write,
m_position);
630 if (file_bytes_written < 0) {
631 DEBUG_LOG <<
"File::write(): "
635 else if (file_bytes_written == 0) {
640 bytes_written += file_bytes_written;
644 return bytes_written;
648 const void* input_buffer,
649 mi::Uint64 num_bytes_to_write)
657 DEBUG_LOG <<
"File::flush_buffers(): "
658 <<
"write access on invalid file handle.";
666 virtual mi::Uint64
size()
const
683 std::string ret_error;
685 case EBADF: ret_error.assign(
"invalid file descriptor");
break;
686 case EINVAL: ret_error.assign(
"invalid direction specified on lseek");
break;
687 case EOVERFLOW: ret_error.assign(
"overflow on returned offset");
break;
688 case ESPIPE: ret_error.assign(
"file descripor is associated with a pipe, socket, or FIFO");
break;
689 default: ret_error.assign(
"unknown error");
break;
691 DEBUG_LOG <<
"File::actual_file_size(): "
692 <<
"error retrieving file size "
693 <<
"(" << ret_error <<
")"
732 std::ios_base::openmode open_mode,
733 mi::Uint32 file_flags)
735 std::string open_flags;
736 if (open_mode == std::ios_base::in)
740 else if (open_mode == std::ios_base::out)
746 ERROR_LOG <<
"File::open(): "
747 <<
"illegal open mode 0x" << std::hex << open_mode
748 <<
" for use with gzip on file "
753 std::ostringstream os;
781 m_open_mode =
static_cast<std::ios_base::openmode
>(0);
785 virtual mi::Uint64
read(
void* output_buffer,
786 mi::Uint64 start_position,
787 mi::Uint64 num_bytes_to_read)
790 DEBUG_LOG <<
"File::read(): "
791 <<
"read access on invalid file handle.";
797 ERROR_LOG <<
"Can't seek in gzip file, requested position is " << start_position <<
" "
798 <<
"while current position is " <<
m_position;
804 Uint8* output_byte_buffer =
reinterpret_cast<Uint8*
>(output_buffer);
805 Uint64 bytes_read = 0;
807 if (num_bytes_to_read <= 0) {
811 int file_bytes_read = 0;
812 unsigned file_bytes_to_read =
static_cast<unsigned>(num_bytes_to_read);
813 file_bytes_read = gzread(
m_gz_handle, output_byte_buffer, file_bytes_to_read);
815 if (file_bytes_read <= 0) {
816 DEBUG_LOG <<
"File::read(): "
821 if (
static_cast<Uint64
>(file_bytes_read) <= num_bytes_to_read) {
823 bytes_read = file_bytes_read;
826 DEBUG_LOG <<
"File::read(): "
827 <<
"unknown error reading from file " <<
m_file_path;
830 assert(bytes_read > 0);
837 mi::Uint64 num_bytes_to_read)
842 virtual mi::Uint64
write(
const void* input_buffer,
843 mi::Uint64 start_position,
844 mi::Uint64 num_bytes_to_write)
849 DEBUG_LOG <<
"File::write(): "
850 <<
"write access on invalid file handle.";
856 ERROR_LOG <<
"Can't seek in gzip file, requested position is " << start_position <<
" "
857 <<
"while current position is " <<
m_position;
861 const Uint8* input_byte_buffer =
reinterpret_cast<const Uint8*
>(input_buffer);
862 Uint64 bytes_written = 0;
864 int file_bytes_written = 0;
865 unsigned file_bytes_to_write =
static_cast<unsigned>(num_bytes_to_write);
866 file_bytes_written = gzwrite(
m_gz_handle, input_byte_buffer, file_bytes_to_write);
868 if (file_bytes_written <= 0) {
869 DEBUG_LOG <<
"File::write(): "
874 if (
static_cast<Uint64
>(file_bytes_written) <= num_bytes_to_write) {
876 bytes_written = file_bytes_written;
879 DEBUG_LOG <<
"File::write(): "
880 <<
"unknown error writing to file " <<
m_file_path;
884 return bytes_written;
888 const void* input_buffer,
889 mi::Uint64 num_bytes_to_write)
897 DEBUG_LOG <<
"File::flush_buffers(): "
898 <<
"write access on invalid file handle.";
907 virtual mi::Uint64
size()
const
909 ERROR_LOG <<
"size() no implemented for gzip";
920 ERROR_LOG <<
"actual_file_size() no implemented for gzip";
937 if (gzip_compression_level == 0)
947 std::ios_base::openmode open_mode,
948 mi::Uint32 file_flags)
964 std::ios_base::openmode open_mode,
965 mi::Uint32 file_flags)
990 mi::Uint64 start_position,
991 mi::Uint64 num_bytes_to_read)
994 return m_file_impl->
read(output_buffer, start_position, num_bytes_to_read);
998 mi::Uint64 start_position,
999 mi::Uint64 num_bytes_to_write)
1002 return m_file_impl->
write(input_buffer, start_position, num_bytes_to_write);
1006 mi::Uint64 num_bytes_to_read)
1013 mi::Uint64 num_bytes_to_write)
1037File::operator bool()
const
virtual bool is_open() const
virtual mi::Uint64 actual_file_size() const
virtual mi::Uint64 write(const void *input_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_write)
virtual bool open(const std::string &file_path, std::ios_base::openmode open_mode, mi::Uint32 file_flags)
mi::Uint64 read_plain(void *output_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_read)
virtual bool flush_buffers() const
virtual const std::string & file_path() const
virtual mi::Uint64 write(const void *input_buffer, mi::Uint64 num_bytes_to_write)
std::ios_base::openmode m_open_mode
virtual mi::Uint64 read(void *output_buffer, mi::Uint64 num_bytes_to_read)
virtual mi::Uint64 read(void *output_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_read)
virtual mi::Uint64 size() const
mi::Uint64 read_odirect(void *output_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_read)
virtual mi::Uint64 write(const void *input_buffer, mi::Uint64 num_bytes_to_write)
virtual mi::Uint64 size() const
virtual mi::Uint64 write(const void *input_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_write)
virtual ~File_gzip_impl()
File_gzip_impl(mi::Uint32 compression_level)
virtual mi::Uint64 read(void *output_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_read)
virtual const std::string & file_path() const
virtual bool is_open() const
virtual bool open(const std::string &file_path, std::ios_base::openmode open_mode, mi::Uint32 file_flags)
virtual mi::Uint64 read(void *output_buffer, mi::Uint64 num_bytes_to_read)
mi::Uint32 m_compression_level
virtual bool flush_buffers() const
virtual mi::Uint64 actual_file_size() const
mi::Uint64 write(const void *input_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_write)
bool flush_buffers() const
bool open(const std::string &file_path, std::ios_base::openmode open_mode=std::ios_base::in|std::ios_base::out, mi::Uint32 file_flags=FILE_FLAG_NONE)
mi::Uint64 read(void *output_buffer, mi::Uint64 start_position, mi::Uint64 num_bytes_to_read)
@ FILE_FLAG_SEQUENTIAL_READ
@ FILE_FLAG_NO_SYSTEM_CACHE
const std::string & file_path() const
File abstraction for transparent handling of large (>4GiB) on Linux and Windows platforms.
bool file_exists(const std::string &file_path)