Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
* Distributed under the OSI-approved Apache License, Version 2.0. See
* accompanying file Copyright.txt for details.
*
* FileStdio.cpp
*
* Created on: Jan 6, 2017
* Author: William F Godoy godoywf@ornl.gov
*/
#include "FileStdio.h"
/// \cond EXCLUDE_FROM_DOXYGEN
#include <ios> //std::ios_base::failure
/// \endcond
// removes fopen warning on Windows
#ifdef _WIN32
#pragma warning(disable : 4996) // fopen
#endif
namespace adios2
{
namespace transport
{
FileStdio::FileStdio(MPI_Comm mpiComm, const bool debugMode)
: Transport("File", "stdio", mpiComm, debugMode)
{
}
FileStdio::~FileStdio()
{
if (m_IsOpen)
{
std::fclose(m_File);
}
}
void FileStdio::Open(const std::string &name, const Mode openMode)
{
m_Name = name;
CheckName();
m_OpenMode = openMode;
switch (m_OpenMode)
{
case (Mode::Write):
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
m_File = std::fopen(name.c_str(), "wb");
break;
case (Mode::Append):
m_File = std::fopen(name.c_str(), "rwb");
break;
case (Mode::Read):
m_File = std::fopen(name.c_str(), "rb");
break;
default:
CheckFile("unknown open mode for file " + m_Name +
", in call to stdio fopen");
}
CheckFile("couldn't open file " + m_Name +
", check permissions or path existence, in call to stdio open");
m_IsOpen = true;
}
void FileStdio::SetBuffer(char *buffer, size_t size)
{
const int status = std::setvbuf(m_File, buffer, _IOFBF, size);
if (!status)
{
throw std::ios_base::failure(
"ERROR: could not set FILE* buffer in file " + m_Name +
", in call to stdio setvbuf\n");
}
}
void FileStdio::Write(const char *buffer, size_t size, size_t start)
{
auto lf_Write = [&](const char *buffer, size_t size) {
ProfilerStart("write");
auto writtenSize = std::fwrite(buffer, sizeof(char), size, m_File);
ProfilerStop("write");
CheckFile("couldn't write to file " + m_Name +
", in call to stdio fwrite");
if (writtenSize != size)
{
throw std::ios_base::failure(
"ERROR: written size + " + std::to_string(writtenSize) +
" is not equal to intended size " + std::to_string(size) +
" in file " + m_Name + ", in call to stdio fwrite\n");
}
};
if (start != MaxSizeT)
{
std::fseek(m_File, static_cast<long int>(start), SEEK_SET);
CheckFile("couldn't move to start position " + std::to_string(start) +
" in file " + m_Name + ", in call to stdio fseek at write ");
}
if (size > DefaultMaxFileBatchSize)
{
const size_t batches = size / DefaultMaxFileBatchSize;
const size_t remainder = size % DefaultMaxFileBatchSize;
size_t position = 0;
for (size_t b = 0; b < batches; ++b)
{
lf_Write(&buffer[position], DefaultMaxFileBatchSize);
position += DefaultMaxFileBatchSize;
}
lf_Write(&buffer[position], remainder);
}
else
{
lf_Write(buffer, size);
}
}
void FileStdio::Read(char *buffer, size_t size, size_t start)
{
auto lf_Read = [&](char *buffer, size_t size) {
ProfilerStart("read");
auto readSize = std::fread(buffer, sizeof(char), size, m_File);
ProfilerStop("read");
CheckFile("couldn't read to file " + m_Name +
", in call to stdio fread");
if (readSize != size)
{
throw std::ios_base::failure(
"ERROR: read size + " + std::to_string(readSize) +
" is not equal to intended size " + std::to_string(size) +
" in file " + m_Name + ", in call to stdio fread\n");
}
};
if (start != MaxSizeT)
{
const auto result =
std::fseek(m_File, static_cast<long int>(start), SEEK_SET);
CheckFile("couldn't move to start position " + std::to_string(start) +
" in file " + m_Name +
", in call to stdio fseek for read, result=" +
std::to_string(result));
}
if (size > DefaultMaxFileBatchSize)
{
const size_t batches = size / DefaultMaxFileBatchSize;
const size_t remainder = size % DefaultMaxFileBatchSize;
size_t position = 0;
for (size_t b = 0; b < batches; ++b)
{
lf_Read(&buffer[position], DefaultMaxFileBatchSize);
position += DefaultMaxFileBatchSize;
}
lf_Read(&buffer[position], remainder);
}
else
{
lf_Read(buffer, size);
}
}
size_t FileStdio::GetSize()
{
const auto currentPosition = ftell(m_File);
fseek(m_File, 0, SEEK_END);
const auto size = ftell(m_File);
if (size == -1)
{
throw std::ios_base::failure("ERROR: couldn't get size of " + m_Name +
" file\n");
}
fseek(m_File, currentPosition, SEEK_SET);
return static_cast<size_t>(size);
}
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
void FileStdio::Flush()
{
const int status = std::fflush(m_File);
if (status == EOF)
{
throw std::ios_base::failure("ERROR: couldn't flush file " + m_Name +
", in call to stdio fflush\n");
}
}
void FileStdio::Close()
{
ProfilerStart("close");
const int status = std::fclose(m_File);
ProfilerStop("close");
if (status == EOF)
{
throw std::ios_base::failure("ERROR: couldn't close file " + m_Name +
", in call to stdio fclose\n");
}
m_IsOpen = false;
}
void FileStdio::CheckFile(const std::string hint) const
{
if (std::ferror(m_File))
{
throw std::ios_base::failure("ERROR: " + hint + "\n");
}
}
} // end namespace transport
} // end namespace adios2