Skip to content

Commit 0b6cb96

Browse files
authored
Merge pull request #234 from Flamefire/master
Make filename creation consistent
2 parents 467c85e + 4f6e7e6 commit 0b6cb96

13 files changed

+741
-77
lines changed

src/HandleMgr.cpp

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2013 Felix Schmitt
2+
* Copyright 2013-2016 Felix Schmitt, Alexander Grund
33
*
44
* This file is part of libSplash.
55
*
@@ -27,17 +27,17 @@
2727
#include <hdf5.h>
2828

2929
#include "splash/core/HandleMgr.hpp"
30+
#include "splash/core/logging.hpp"
31+
#include "splash/core/DCHelper.hpp"
3032

3133
namespace splash
3234
{
3335

3436
HandleMgr::HandleMgr(uint32_t maxHandles, FileNameScheme fileNameScheme) :
3537
maxHandles(maxHandles),
36-
numHandles(0),
3738
mpiSize(1, 1, 1),
3839
fileNameScheme(fileNameScheme),
3940
fileFlags(0),
40-
singleFile(true),
4141
fileCreateCallback(NULL),
4242
fileCreateUserData(NULL),
4343
fileOpenCallback(NULL),
@@ -69,26 +69,53 @@ namespace splash
6969
return full_msg.str();
7070
}
7171

72+
void HandleMgr::setFileNameScheme(FileNameScheme fileNameScheme) throw (DCException)
73+
{
74+
if (this->fileNameScheme == fileNameScheme)
75+
return;
76+
if (!filename.empty())
77+
throw DCException(getExceptionString("setFileNameScheme",
78+
"Tried to change scheme while file(s) were still open", ""));
79+
this->fileNameScheme = fileNameScheme;
80+
}
81+
7282
void HandleMgr::open(Dimensions mpiSize, const std::string baseFilename,
7383
hid_t fileAccProperties, unsigned flags)
84+
throw (DCException)
7485
{
75-
this->numHandles = mpiSize.getScalarSize();
7686
this->mpiSize.set(mpiSize);
7787
this->filename = baseFilename;
7888
this->fileAccProperties = fileAccProperties;
7989
this->fileFlags = flags;
80-
this->singleFile = false;
90+
// Validation: For parallel files we normally append MPI rank or iteration number.
91+
// This is disabled by using FNS_FULLNAME
92+
// or when the filename already contains an h5-extension.
93+
if (fileNameScheme != FNS_FULLNAME && baseFilename.find(".h5") == baseFilename.length() - 3)
94+
{
95+
if (mpiSize.getScalarSize() > 1)
96+
{
97+
throw DCException(getExceptionString("open",
98+
"Passed full filename for parallel file operations",
99+
baseFilename.c_str()));
100+
} else
101+
{
102+
log_msg(1, "\n"
103+
"\tWarning: Passed full filename for parallel file operations: %s\n"
104+
"It is recommended to pass only the base name (no extension)"
105+
"and let the implementation choose a filename.\n", filename.c_str());
106+
}
107+
}
81108
}
82109

83110
void HandleMgr::open(const std::string fullFilename,
84111
hid_t fileAccProperties, unsigned flags)
112+
throw (DCException)
85113
{
86-
this->numHandles = 1;
114+
setFileNameScheme(FNS_FULLNAME);
87115
this->mpiSize.set(1, 1, 1);
88116
this->filename = fullFilename;
89117
this->fileAccProperties = fileAccProperties;
90118
this->fileFlags = flags;
91-
this->singleFile = true;
92119
}
93120

94121
uint32_t HandleMgr::indexFromPos(Dimensions& mpiPos)
@@ -125,7 +152,7 @@ namespace splash
125152
throw (DCException)
126153
{
127154
uint32_t index = 0;
128-
if (!singleFile)
155+
if (fileNameScheme != FNS_FULLNAME)
129156
index = indexFromPos(mpiPos);
130157

131158
HandleMap::iterator iter = handles.find(index);
@@ -150,28 +177,34 @@ namespace splash
150177
leastAccIndex.ctr = 0;
151178
}
152179

153-
std::stringstream filenameStream;
154-
filenameStream << filename;
155-
if (!singleFile)
180+
// Append prefix and extension if we don't have a full filename (extension)
181+
std::string fullFilename;
182+
if (fileNameScheme != FNS_FULLNAME && filename.find(".h5") != filename.length() - 3)
156183
{
184+
std::stringstream filenameStream;
185+
filenameStream << filename;
157186
if (fileNameScheme == FNS_MPI)
158187
{
159188
filenameStream << "_" << mpiPos[0] << "_" << mpiPos[1] <<
160189
"_" << mpiPos[2] << ".h5";
161-
} else
190+
} else if(fileNameScheme == FNS_ITERATIONS)
162191
filenameStream << "_" << mpiPos[0] << ".h5";
163-
}
192+
fullFilename = filenameStream.str();
193+
}else
194+
fullFilename = filename;
164195

165196
H5Handle newHandle = 0;
166197

167198
// serve requests to create files once as create and as read/write afterwards
168199
if ((fileFlags & H5F_ACC_TRUNC) && (createdFiles.find(index) == createdFiles.end()))
169200
{
170-
newHandle = H5Fcreate(filenameStream.str().c_str(), fileFlags,
201+
DCHelper::testFilename(fullFilename);
202+
203+
newHandle = H5Fcreate(fullFilename.c_str(), fileFlags,
171204
H5P_FILE_CREATE_DEFAULT, fileAccProperties);
172205
if (newHandle < 0)
173206
throw DCException(getExceptionString("get", "Failed to create file",
174-
filenameStream.str().c_str()));
207+
fullFilename.c_str()));
175208

176209
createdFiles.insert(index);
177210

@@ -184,10 +217,10 @@ namespace splash
184217
if (fileFlags & H5F_ACC_TRUNC)
185218
tmp_flags = H5F_ACC_RDWR;
186219

187-
newHandle = H5Fopen(filenameStream.str().c_str(), tmp_flags, fileAccProperties);
220+
newHandle = H5Fopen(fullFilename.c_str(), tmp_flags, fileAccProperties);
188221
if (newHandle < 0)
189222
throw DCException(getExceptionString("get", "Failed to open file",
190-
filenameStream.str().c_str()));
223+
fullFilename.c_str()));
191224

192225
if (fileOpenCallback)
193226
fileOpenCallback(newHandle, index, fileOpenUserData);
@@ -224,8 +257,6 @@ namespace splash
224257
leastAccIndex.ctr = 0;
225258
leastAccIndex.index = 0;
226259
mpiSize.set(1, 1, 1);
227-
numHandles = 0;
228-
singleFile = true;
229260

230261
// close all remaining handles
231262
HandleMap::const_iterator iter = handles.begin();

src/ParallelDataCollector.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2013-2015 Felix Schmitt, Axel Huebl
2+
* Copyright 2013-2016 Felix Schmitt, Axel Huebl, Alexander Grund
33
*
44
* This file is part of libSplash.
55
*
@@ -67,14 +67,6 @@ namespace splash
6767
log_msg(3, "Raw Data Cache (File) = %llu KiB", (long long unsigned) (rawCacheSize / 1024));
6868
}
6969

70-
std::string ParallelDataCollector::getFullFilename(uint32_t id, std::string baseFilename)
71-
{
72-
std::stringstream serial_filename;
73-
serial_filename << baseFilename << "_" << id << ".h5";
74-
75-
return serial_filename.str();
76-
}
77-
7870
std::string ParallelDataCollector::getExceptionString(std::string func, std::string msg,
7971
const char *info)
8072
{
@@ -201,15 +193,16 @@ namespace splash
201193

202194
ParallelDataCollector::~ParallelDataCollector()
203195
{
196+
close();
204197
H5Pclose(fileAccProperties);
198+
finalize();
205199
}
206200

207201
void ParallelDataCollector::finalize()
208202
{
209-
log_msg(1, "finalizing data collector");
210-
211203
if (options.mpiComm != MPI_COMM_NULL)
212204
{
205+
log_msg(1, "finalizing data collector");
213206
MPI_Comm_free(&options.mpiComm);
214207
options.mpiComm = MPI_COMM_NULL;
215208
}
@@ -245,6 +238,9 @@ namespace splash
245238

246239
void ParallelDataCollector::close()
247240
{
241+
if (fileStatus == FST_CLOSED)
242+
return;
243+
248244
log_msg(1, "closing parallel data collector");
249245

250246
// close opened hdf5 file handles

src/SerialDataCollector.cpp

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2013-2015 Felix Schmitt, Axel Huebl
2+
* Copyright 2013-2016 Felix Schmitt, Axel Huebl, Alexander Grund
33
*
44
* This file is part of libSplash.
55
*
@@ -35,7 +35,6 @@
3535
#include "splash/core/DCAttribute.hpp"
3636
#include "splash/core/DCDataSet.hpp"
3737
#include "splash/core/DCGroup.hpp"
38-
#include "splash/core/DCHelper.hpp"
3938
#include "splash/core/SDCHelper.hpp"
4039
#include "splash/core/logging.hpp"
4140
#include "splash/basetypes/basetypes.hpp"
@@ -70,8 +69,18 @@ namespace splash
7069
return (stat(filename.c_str(), &fileInfo) == 0);
7170
}
7271

73-
std::string SerialDataCollector::getFullFilename(const Dimensions mpiPos, std::string baseFilename) const
72+
std::string SerialDataCollector::getFullFilename(const Dimensions mpiPos, std::string baseFilename,
73+
bool isFullNameAllowed) const throw (DCException)
7474
{
75+
// Check for existing extension
76+
if (baseFilename.find(".h5") == baseFilename.length() - 3)
77+
{
78+
if (isFullNameAllowed)
79+
return baseFilename;
80+
else
81+
throw DCException("Full filename is not allowed!");
82+
}
83+
7584
std::stringstream serial_filename;
7685
serial_filename << baseFilename << "_" << mpiPos[0] << "_" << mpiPos[1] <<
7786
"_" << mpiPos[2] << ".h5";
@@ -97,7 +106,7 @@ namespace splash
97106
*******************************************************************************/
98107

99108
SerialDataCollector::SerialDataCollector(uint32_t maxFileHandles) :
100-
handles(maxFileHandles, HandleMgr::FNS_MPI),
109+
handles(maxFileHandles, HandleMgr::FNS_FULLNAME),
101110
fileStatus(FST_CLOSED),
102111
maxID(-1),
103112
mpiTopology(1, 1, 1)
@@ -113,7 +122,7 @@ namespace splash
113122
"failed to initialize/open HDF5 library"));
114123

115124
#ifndef SPLASH_VERBOSE_HDF5
116-
// surpress automatic output of HDF5 exception messages
125+
// Suppress automatic output of HDF5 exception messages
117126
if (H5Eset_auto2(H5E_DEFAULT, NULL, NULL) < 0)
118127
throw DCException(getExceptionString("SerialDataCollector",
119128
"failed to disable error printing"));
@@ -125,6 +134,7 @@ namespace splash
125134

126135
SerialDataCollector::~SerialDataCollector()
127136
{
137+
close();
128138
}
129139

130140
void SerialDataCollector::open(const char* filename, FileCreationAttr &attr)
@@ -157,16 +167,19 @@ namespace splash
157167

158168
void SerialDataCollector::close()
159169
{
170+
if (fileStatus == FST_CLOSED)
171+
return;
172+
160173
log_msg(1, "closing serial data collector");
161174

162-
if (fileStatus == FST_CREATING || fileStatus == FST_WRITING)
175+
if ((fileStatus == FST_CREATING || fileStatus == FST_WRITING) &&
176+
maxID >= 0)
163177
{
164-
DCGroup group;
165-
group.open(handles.get(0), SDC_GROUP_HEADER);
166-
167178
// write number of iterations
168179
try
169180
{
181+
DCGroup group;
182+
group.open(handles.get(0), SDC_GROUP_HEADER);
170183
ColTypeInt32 ctInt32;
171184
DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, ctInt32.getDataType(),
172185
group.getHandle(), &maxID);
@@ -746,9 +759,8 @@ namespace splash
746759
{
747760
this->fileStatus = FST_CREATING;
748761

749-
// appends the mpiPosition to the filename (e.g. myfile_0_1_0.h5)
750-
std::string full_filename = getFullFilename(attr.mpiPosition, filename);
751-
DCHelper::testFilename(full_filename);
762+
std::string full_filename = getFullFilename(attr.mpiPosition, filename,
763+
attr.mpiSize.getScalarSize() == 1);
752764

753765
this->enableCompression = attr.enableCompression;
754766

@@ -779,11 +791,8 @@ namespace splash
779791
{
780792
fileStatus = FST_WRITING;
781793

782-
std::string full_filename = filename;
783-
if (full_filename.find(".h5") == std::string::npos)
784-
full_filename = getFullFilename(attr.mpiPosition, filename);
785-
786-
DCHelper::testFilename(full_filename);
794+
std::string full_filename = getFullFilename(attr.mpiPosition, filename,
795+
attr.mpiSize.getScalarSize() == 1);
787796

788797
this->enableCompression = attr.enableCompression;
789798

@@ -805,9 +814,7 @@ namespace splash
805814
this->fileStatus = FST_MERGING;
806815

807816
// open reference file to get mpi information
808-
std::string full_filename = getFullFilename(Dimensions(0, 0, 0), filename);
809-
810-
DCHelper::testFilename(full_filename);
817+
std::string full_filename = getFullFilename(Dimensions(0, 0, 0), filename, true);
811818

812819
if (!fileExists(full_filename))
813820
{
@@ -821,6 +828,7 @@ namespace splash
821828
// no compression for in-memory datasets
822829
this->enableCompression = false;
823830

831+
handles.setFileNameScheme(HandleMgr::FNS_MPI);
824832
handles.open(mpiTopology, filename, fileAccProperties, H5F_ACC_RDONLY);
825833
}
826834

@@ -829,11 +837,7 @@ namespace splash
829837
{
830838
this->fileStatus = FST_READING;
831839

832-
std::string full_filename = filename;
833-
if (full_filename.find(".h5") == std::string::npos)
834-
full_filename = getFullFilename(attr.mpiPosition, filename);
835-
836-
DCHelper::testFilename(full_filename);
840+
std::string full_filename = getFullFilename(attr.mpiPosition, filename, true);
837841

838842
if (!fileExists(full_filename))
839843
{

src/include/splash/ParallelDataCollector.hpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,6 @@ namespace splash
5454
*/
5555
void setFileAccessParams(hid_t& fileAccProperties);
5656

57-
/**
58-
* Constructs a filename from a base filename and the current id
59-
* such as baseFilename+id+.h5
60-
*
61-
* @param id Iteration ID.
62-
* @param baseFilename Base filename for the new file.
63-
* @return newly Constructed filename including file extension.
64-
*/
65-
static std::string getFullFilename(uint32_t id, std::string baseFilename);
66-
6757
/**
6858
* Internal function for formatting exception messages.
6959
*

src/include/splash/SerialDataCollector.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,17 @@ namespace splash
6060

6161
/**
6262
* Constructs a filename from a base filename and the process' mpi position
63-
* such as baseFilename+mpiPos+.h5
63+
* such as myfile_0_1_0.h5
64+
* Does nothing if the filename already ends with ".h5" (only allowed
65+
* for Prod(mpiSize)==1 or reading).
6466
*
6567
* @param mpiPos MPI position of the process
6668
* @param baseFilename base filename for the new file
67-
* @return newly constructed filename iucluding file exitension
69+
* @param isFullNameAllowed If false, an exception is raised when a full name is passed
70+
* @return newly constructed filename including file extension
6871
*/
69-
std::string getFullFilename(const Dimensions mpiPos, std::string baseFilename) const;
72+
std::string getFullFilename(const Dimensions mpiPos, std::string baseFilename,
73+
bool isFullNameAllowed) const throw (DCException);
7074

7175
/**
7276
* Internal function for formatting exception messages.

0 commit comments

Comments
 (0)