ENH: use atomic move in wmkdepend

- avoids truncated files if dependency generation is interrupted
This commit is contained in:
Mark Olesen
2022-09-08 16:56:00 +02:00
parent 793f4e3a37
commit c841aaed83
2 changed files with 111 additions and 69 deletions

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2020 OpenCFD Ltd. Copyright (C) 2018-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -112,6 +112,8 @@ bool optVerbose = false;
//- The top-level source file being processed //- The top-level source file being processed
std::string sourceFile; std::string sourceFile;
//- The output stream
FILE* output = stdout;
//- All file opening and writing //- All file opening and writing
namespace Files namespace Files
@ -185,7 +187,7 @@ namespace Files
} }
//- Open a file for reading and emit its qualified name to stdout. //- Open a file for reading and emit its qualified name to output.
// //
// Uses env substitutions at the beginning of the path // Uses env substitutions at the beginning of the path
// //
@ -215,13 +217,13 @@ namespace Files
) )
{ {
fname += entry.len; // Now positioned after the '/' fname += entry.len; // Now positioned after the '/'
fputs(entry.name.c_str(), stdout); fputs(entry.name.c_str(), output);
break; break;
} }
} }
fputs(fname, stdout); fputs(fname, output);
fputs(" \\\n", stdout); fputs(" \\\n", output);
} }
else if (errno == EMFILE) else if (errno == EMFILE)
{ {
@ -314,14 +316,14 @@ namespace Files
// Can use 'variable p xxx;' etc to change these names // Can use 'variable p xxx;' etc to change these names
#line 318 "wmkdepend.cc" #line 320 "wmkdepend.cc"
static const int wmkdep_start = 21; static const int wmkdep_start = 21;
static const int wmkdep_error = 0; static const int wmkdep_error = 0;
static const int wmkdep_en_main = 21; static const int wmkdep_en_main = 21;
#line 344 "wmkdepend.rl" #line 346 "wmkdepend.rl"
@ -362,7 +364,7 @@ void processFile(std::string fileName)
// Initialize FSM variables // Initialize FSM variables
#line 366 "wmkdepend.cc" #line 368 "wmkdepend.cc"
{ {
cs = wmkdep_start; cs = wmkdep_start;
ts = 0; ts = 0;
@ -370,7 +372,7 @@ void processFile(std::string fileName)
act = 0; act = 0;
} }
#line 383 "wmkdepend.rl" #line 385 "wmkdepend.rl"
/* ^^^ FSM initialization here ^^^ */; /* ^^^ FSM initialization here ^^^ */;
// Local token start // Local token start
@ -415,7 +417,7 @@ void processFile(std::string fileName)
} }
#line 419 "wmkdepend.cc" #line 421 "wmkdepend.cc"
{ {
if ( p == pe ) if ( p == pe )
goto _test_eof; goto _test_eof;
@ -434,35 +436,35 @@ tr0:
} }
goto st21; goto st21;
tr2: tr2:
#line 342 "wmkdepend.rl" #line 344 "wmkdepend.rl"
{te = p+1;} {te = p+1;}
goto st21; goto st21;
tr17: tr17:
#line 342 "wmkdepend.rl" #line 344 "wmkdepend.rl"
{{p = ((te))-1;}} {{p = ((te))-1;}}
goto st21; goto st21;
tr21: tr21:
#line 337 "wmkdepend.rl"
{te = p+1;}
goto st21;
tr29:
#line 340 "wmkdepend.rl"
{te = p+1;}
goto st21;
tr31:
#line 339 "wmkdepend.rl" #line 339 "wmkdepend.rl"
{te = p+1;} {te = p+1;}
goto st21; goto st21;
tr29:
#line 342 "wmkdepend.rl"
{te = p+1;}
goto st21;
tr31:
#line 341 "wmkdepend.rl"
{te = p+1;}
goto st21;
tr36: tr36:
#line 334 "wmkdepend.rl" #line 336 "wmkdepend.rl"
{te = p;p--;} {te = p;p--;}
goto st21; goto st21;
tr37: tr37:
#line 342 "wmkdepend.rl" #line 344 "wmkdepend.rl"
{te = p;p--;} {te = p;p--;}
goto st21; goto st21;
tr38: tr38:
#line 340 "wmkdepend.rl" #line 342 "wmkdepend.rl"
{te = p;p--;} {te = p;p--;}
goto st21; goto st21;
st21: st21:
@ -475,7 +477,7 @@ st21:
case 21: case 21:
#line 1 "NONE" #line 1 "NONE"
{ts = p;} {ts = p;}
#line 479 "wmkdepend.cc" #line 481 "wmkdepend.cc"
switch( (*p) ) { switch( (*p) ) {
case 10: goto st23; case 10: goto st23;
case 11: goto tr34; case 11: goto tr34;
@ -496,14 +498,14 @@ case 1:
tr32: tr32:
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}
#line 334 "wmkdepend.rl" #line 336 "wmkdepend.rl"
{act = 1;} {act = 1;}
goto st22; goto st22;
st22: st22:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof22; goto _test_eof22;
case 22: case 22:
#line 507 "wmkdepend.cc" #line 509 "wmkdepend.cc"
switch( (*p) ) { switch( (*p) ) {
case 10: goto st23; case 10: goto st23;
case 11: goto tr34; case 11: goto tr34;
@ -525,14 +527,14 @@ case 23:
tr34: tr34:
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}
#line 334 "wmkdepend.rl" #line 336 "wmkdepend.rl"
{act = 1;} {act = 1;}
goto st24; goto st24;
st24: st24:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof24; goto _test_eof24;
case 24: case 24:
#line 536 "wmkdepend.cc" #line 538 "wmkdepend.cc"
switch( (*p) ) { switch( (*p) ) {
case 10: goto st23; case 10: goto st23;
case 32: goto tr34; case 32: goto tr34;
@ -630,14 +632,14 @@ case 10:
} }
goto tr12; goto tr12;
tr12: tr12:
#line 318 "wmkdepend.rl" #line 320 "wmkdepend.rl"
{ tok = p; /* Local token start */ } { tok = p; /* Local token start */ }
goto st11; goto st11;
st11: st11:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof11; goto _test_eof11;
case 11: case 11:
#line 641 "wmkdepend.cc" #line 643 "wmkdepend.cc"
switch( (*p) ) { switch( (*p) ) {
case 10: goto tr15; case 10: goto tr15;
case 34: goto tr16; case 34: goto tr16;
@ -646,7 +648,7 @@ case 11:
tr13: tr13:
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}
#line 318 "wmkdepend.rl" #line 320 "wmkdepend.rl"
{ tok = p; /* Local token start */ } { tok = p; /* Local token start */ }
goto st25; goto st25;
tr15: tr15:
@ -657,7 +659,7 @@ st25:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof25; goto _test_eof25;
case 25: case 25:
#line 661 "wmkdepend.cc" #line 663 "wmkdepend.cc"
if ( (*p) == 34 ) if ( (*p) == 34 )
goto tr19; goto tr19;
goto st12; goto st12;
@ -669,7 +671,7 @@ case 12:
goto tr19; goto tr19;
goto st12; goto st12;
tr19: tr19:
#line 320 "wmkdepend.rl" #line 322 "wmkdepend.rl"
{ {
processFile(tok, p); processFile(tok, p);
tok = nullptr; /* Done with buffer */ tok = nullptr; /* Done with buffer */
@ -679,12 +681,12 @@ st13:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof13; goto _test_eof13;
case 13: case 13:
#line 683 "wmkdepend.cc" #line 685 "wmkdepend.cc"
if ( (*p) == 10 ) if ( (*p) == 10 )
goto tr21; goto tr21;
goto st13; goto st13;
tr16: tr16:
#line 320 "wmkdepend.rl" #line 322 "wmkdepend.rl"
{ {
processFile(tok, p); processFile(tok, p);
tok = nullptr; /* Done with buffer */ tok = nullptr; /* Done with buffer */
@ -694,7 +696,7 @@ st14:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof14; goto _test_eof14;
case 14: case 14:
#line 698 "wmkdepend.cc" #line 700 "wmkdepend.cc"
if ( (*p) == 10 ) if ( (*p) == 10 )
goto tr21; goto tr21;
goto st14; goto st14;
@ -725,7 +727,7 @@ st26:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof26; goto _test_eof26;
case 26: case 26:
#line 729 "wmkdepend.cc" #line 731 "wmkdepend.cc"
if ( (*p) == 42 ) if ( (*p) == 42 )
goto st18; goto st18;
goto st17; goto st17;
@ -758,14 +760,14 @@ case 19:
tr30: tr30:
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}
#line 340 "wmkdepend.rl" #line 342 "wmkdepend.rl"
{act = 4;} {act = 4;}
goto st27; goto st27;
st27: st27:
if ( ++p == pe ) if ( ++p == pe )
goto _test_eof27; goto _test_eof27;
case 27: case 27:
#line 769 "wmkdepend.cc" #line 771 "wmkdepend.cc"
if ( (*p) == 10 ) if ( (*p) == 10 )
goto tr2; goto tr2;
goto st1; goto st1;
@ -840,7 +842,7 @@ cs = 0;
_out: {} _out: {}
} }
#line 426 "wmkdepend.rl" #line 428 "wmkdepend.rl"
/* ^^^ FSM execution here ^^^ */; /* ^^^ FSM execution here ^^^ */;
if (0 == cs) if (0 == cs)
@ -877,10 +879,12 @@ cs = 0;
pending = 0; pending = 0;
} }
} }
fclose(infile); ::fclose(infile);
} }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if (argc < 2) if (argc < 2)
@ -927,7 +931,7 @@ int main(int argc, char* argv[])
// Verify that input file has an extension // Verify that input file has an extension
{ {
auto dot = sourceFile.find_last_of("./"); const auto dot = sourceFile.find_last_of("./");
if (dot == std::string::npos || sourceFile[dot] != '.') if (dot == std::string::npos || sourceFile[dot] != '.')
{ {
std::cerr std::cerr
@ -979,22 +983,39 @@ int main(int argc, char* argv[])
} }
} }
if (outputFile.size() && !freopen(outputFile.c_str(), "w", stdout))
// Output to an intermediate file
std::string outputTmp;
if (outputFile.length())
{ {
std::cerr outputTmp = outputFile + ".part";
<< EXENAME ": could not open file '"
<< outputFile << "' for output: " << strerror(errno) << "\n"; output = ::fopen(outputTmp.c_str(), "w");
return 1;
if (!output)
{
std::cerr
<< EXENAME ": could not open file '"
<< outputTmp << "' for output: " << strerror(errno) << '\n';
return 1;
}
} }
fputs("$(OBJECTS_DIR)/", stdout); fputs("$(OBJECTS_DIR)/", output);
fputs(sourceFile.c_str(), stdout); fputs(sourceFile.c_str(), output);
fputs(".dep: \\\n", stdout); fputs(".dep: \\\n", output);
processFile(sourceFile); processFile(sourceFile);
fputs("\n#END\n", stdout); fputs("\n#END\n", output);
fflush(stdout); fflush(output);
// Atomic move of intermediate file to final output file
if (outputFile.length())
{
::fclose(output);
::rename(outputTmp.c_str(), outputFile.c_str());
}
return 0; return 0;
} }

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2020 OpenCFD Ltd. Copyright (C) 2018-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -110,6 +110,8 @@ bool optVerbose = false;
//- The top-level source file being processed //- The top-level source file being processed
std::string sourceFile; std::string sourceFile;
//- The output stream
FILE* output = stdout;
//- All file opening and writing //- All file opening and writing
namespace Files namespace Files
@ -183,7 +185,7 @@ namespace Files
} }
//- Open a file for reading and emit its qualified name to stdout. //- Open a file for reading and emit its qualified name to output.
// //
// Uses env substitutions at the beginning of the path // Uses env substitutions at the beginning of the path
// //
@ -213,13 +215,13 @@ namespace Files
) )
{ {
fname += entry.len; // Now positioned after the '/' fname += entry.len; // Now positioned after the '/'
fputs(entry.name.c_str(), stdout); fputs(entry.name.c_str(), output);
break; break;
} }
} }
fputs(fname, stdout); fputs(fname, output);
fputs(" \\\n", stdout); fputs(" \\\n", output);
} }
else if (errno == EMFILE) else if (errno == EMFILE)
{ {
@ -459,10 +461,12 @@ void processFile(std::string fileName)
pending = 0; pending = 0;
} }
} }
fclose(infile); ::fclose(infile);
} }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if (argc < 2) if (argc < 2)
@ -509,7 +513,7 @@ int main(int argc, char* argv[])
// Verify that input file has an extension // Verify that input file has an extension
{ {
auto dot = sourceFile.find_last_of("./"); const auto dot = sourceFile.find_last_of("./");
if (dot == std::string::npos || sourceFile[dot] != '.') if (dot == std::string::npos || sourceFile[dot] != '.')
{ {
std::cerr std::cerr
@ -561,22 +565,39 @@ int main(int argc, char* argv[])
} }
} }
if (outputFile.size() && !freopen(outputFile.c_str(), "w", stdout))
// Output to an intermediate file
std::string outputTmp;
if (outputFile.length())
{ {
std::cerr outputTmp = outputFile + ".part";
<< EXENAME ": could not open file '"
<< outputFile << "' for output: " << strerror(errno) << "\n"; output = ::fopen(outputTmp.c_str(), "w");
return 1;
if (!output)
{
std::cerr
<< EXENAME ": could not open file '"
<< outputTmp << "' for output: " << strerror(errno) << '\n';
return 1;
}
} }
fputs("$(OBJECTS_DIR)/", stdout); fputs("$(OBJECTS_DIR)/", output);
fputs(sourceFile.c_str(), stdout); fputs(sourceFile.c_str(), output);
fputs(".dep: \\\n", stdout); fputs(".dep: \\\n", output);
processFile(sourceFile); processFile(sourceFile);
fputs("\n#END\n", stdout); fputs("\n#END\n", output);
fflush(stdout); fflush(output);
// Atomic move of intermediate file to final output file
if (outputFile.length())
{
::fclose(output);
::rename(outputTmp.c_str(), outputFile.c_str());
}
return 0; return 0;
} }