Skip to content

Commit 1242505

Browse files
committed
Protect counter with mutex
Based on review Making `\dot` and `\msc` independent on the order of processing by means of using the md5 sum of the content (positive side effect when having multiple instances of a `\dot` (or `\msc`) command it is generated just once).
1 parent 7818258 commit 1242505

File tree

10 files changed

+303
-196
lines changed

10 files changed

+303
-196
lines changed

src/docbookvisitor.cpp

Lines changed: 76 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "portable.h"
3636
#include "codefragment.h"
3737
#include "cite.h"
38+
#include "md5.h"
3839

3940
#if 0
4041
#define DB_VIS_C DB_VIS_C1(m_t)
@@ -48,10 +49,10 @@
4849
#define DB_VIS_C2a(x,y)
4950
#endif
5051

51-
static int dotindex = 1;
52-
static std::mutex dotindex_mutex;
53-
static int mscindex = 1;
54-
static std::mutex mscindex_mutex;
52+
static StringVector dotindex;
53+
static std::mutex dotindex_mutex;
54+
static StringVector mscindex;
55+
static std::mutex mscindex_mutex;
5556

5657
static QCString filterId(const QCString &s)
5758
{
@@ -383,59 +384,89 @@ DB_VIS_C
383384
break;
384385
case DocVerbatim::Dot:
385386
{
386-
QCString baseName(4096, QCString::ExplicitSize);
387-
QCString name;
388-
QCString stext = s.text();
389387
m_t << "<para>\n";
388+
QCString stext = s.text();
389+
QCString baseName(4096, QCString::ExplicitSize);
390+
QCString fileName;
391+
392+
uint8_t md5_sig[16];
393+
char sigStr[33];
394+
MD5Buffer(stext.data(),static_cast<unsigned int>(stext.length()),md5_sig);
395+
MD5SigToString(md5_sig,sigStr);
396+
397+
baseName = Config_getString(DOCBOOK_OUTPUT) + "/inline_dotgraph_" + sigStr;
398+
fileName = baseName+".dot";
399+
bool newFile = false;
400+
bool openError = false;
401+
std::lock_guard<std::mutex> lock(dotindex_mutex);
402+
if (std::find(dotindex.begin(), dotindex.end(), sigStr) == dotindex.end())
390403
{
391-
std::lock_guard<std::mutex> lock(dotindex_mutex);
392-
name.sprintf("%s%d", "dot_inline_dotgraph_", dotindex);
393-
baseName.sprintf("%s%d",
394-
qPrint(Config_getString(DOCBOOK_OUTPUT)+"/inline_dotgraph_"),
395-
dotindex++
396-
);
397-
}
398-
QCString fileName = baseName+".dot";
399-
std::ofstream file = Portable::openOutputStream(fileName);
400-
if (!file.is_open())
404+
newFile = true;
405+
dotindex.emplace_back(sigStr);
406+
407+
std::ofstream file = Portable::openOutputStream(fileName);
408+
if (!file.is_open())
409+
{
410+
err("Could not open file {} for writing\n",fileName);
411+
openError = true;
412+
}
413+
else
414+
{
415+
file.write( stext.data(), stext.length() );
416+
file.close();
417+
}
418+
}
419+
if (!openError)
401420
{
402-
err("Could not open file {} for writing\n",fileName);
421+
writeDotFile(baseName, s, newFile);
422+
if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
403423
}
404-
file.write( stext.data(), stext.length() );
405-
file.close();
406-
writeDotFile(baseName, s);
407424
m_t << "</para>\n";
408-
if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
409425
}
410426
break;
411427
case DocVerbatim::Msc:
412428
{
413-
QCString baseName(4096, QCString::ExplicitSize);
414-
QCString name;
415429
QCString stext = s.text();
430+
QCString baseName(4096, QCString::ExplicitSize);
431+
QCString fileName;
416432
m_t << "<para>\n";
433+
434+
uint8_t md5_sig[16];
435+
char sigStr[33];
436+
MD5Buffer(stext.data(),static_cast<unsigned int>(stext.length()),md5_sig);
437+
MD5SigToString(md5_sig,sigStr);
438+
439+
baseName = Config_getString(DOCBOOK_OUTPUT) + "/inline_mscgraph_" + sigStr;
440+
fileName = baseName+".msc";
441+
bool newFile = false;
442+
bool openError = false;
443+
std::lock_guard<std::mutex> lock(mscindex_mutex);
444+
if (std::find(mscindex.begin(), mscindex.end(), sigStr) == mscindex.end())
417445
{
418-
std::lock_guard<std::mutex> lock(mscindex_mutex);
419-
name.sprintf("%s%d", "msc_inline_mscgraph_", mscindex);
420-
baseName.sprintf("%s%d",
421-
(Config_getString(DOCBOOK_OUTPUT)+"/inline_mscgraph_").data(),
422-
mscindex++
423-
);
446+
newFile = true;
447+
mscindex.emplace_back(sigStr);
448+
449+
std::ofstream file = Portable::openOutputStream(fileName);
450+
if (!file.is_open())
451+
{
452+
err("Could not open file {} for writing\n",fileName);
453+
openError = true;
454+
}
455+
else
456+
{
457+
QCString text = "msc {";
458+
text+=stext;
459+
text+="}";
460+
file.write( text.data(), text.length() );
461+
file.close();
462+
}
424463
}
425-
QCString fileName = baseName+".msc";
426-
std::ofstream file = Portable::openOutputStream(fileName);
427-
if (!file.is_open())
464+
if (!openError)
428465
{
429-
err("Could not open file {} for writing\n",fileName);
466+
writeMscFile(baseName,s,newFile);
467+
if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
430468
}
431-
QCString text = "msc {";
432-
text+=stext;
433-
text+="}";
434-
file.write( text.data(), text.length() );
435-
file.close();
436-
writeMscFile(baseName,s);
437469
m_t << "</para>\n";
438-
if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
439470
}
440471
break;
441472
case DocVerbatim::PlantUML:
@@ -1552,12 +1583,12 @@ DB_VIS_C
15521583
m_t << "</link>";
15531584
}
15541585

1555-
void DocbookDocVisitor::writeMscFile(const QCString &baseName, const DocVerbatim &s)
1586+
void DocbookDocVisitor::writeMscFile(const QCString &baseName, const DocVerbatim &s, bool newFile)
15561587
{
15571588
DB_VIS_C
15581589
QCString shortName = makeShortName(baseName);
15591590
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1560-
writeMscGraphFromFile(baseName+".msc",outDir,shortName,MscOutputFormat::BITMAP,s.srcFile(),s.srcLine());
1591+
if (newFile) writeMscGraphFromFile(baseName+".msc",outDir,shortName,MscOutputFormat::BITMAP,s.srcFile(),s.srcLine());
15611592
visitPreStart(m_t, s.children(), s.hasCaption(), s.relPath() + shortName + ".png", s.width(), s.height());
15621593
visitCaption(s.children());
15631594
visitPostEnd(m_t, s.hasCaption());
@@ -1675,12 +1706,12 @@ DB_VIS_C
16751706
m_t << "</para>\n";
16761707
}
16771708

1678-
void DocbookDocVisitor::writeDotFile(const QCString &baseName, const DocVerbatim &s)
1709+
void DocbookDocVisitor::writeDotFile(const QCString &baseName, const DocVerbatim &s, bool newFile)
16791710
{
16801711
DB_VIS_C
16811712
QCString shortName = makeShortName(baseName);
16821713
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1683-
writeDotGraphFromFile(baseName+".dot",outDir,shortName,GraphOutputFormat::BITMAP,s.srcFile(),s.srcLine());
1714+
if (newFile) writeDotGraphFromFile(baseName+".dot",outDir,shortName,GraphOutputFormat::BITMAP,s.srcFile(),s.srcLine());
16841715
visitPreStart(m_t, s.children(), s.hasCaption(), s.relPath() + shortName + "." + getDotImageExtension(), s.width(),s.height());
16851716
visitCaption(s.children());
16861717
visitPostEnd(m_t, s.hasCaption());

src/docbookvisitor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class DocbookDocVisitor : public DocVisitor
118118
const QCString &height, bool hasCaption,const DocNodeList &children,
119119
const QCString &srcFile, int srcLine);
120120
void endMscFile(bool hasCaption);
121-
void writeMscFile(const QCString &fileName, const DocVerbatim &s);
121+
void writeMscFile(const QCString &fileName, const DocVerbatim &s, bool newFile = true);
122122
void startDiaFile(const QCString &fileName,const QCString &relPath, const QCString &width,
123123
const QCString &height, bool hasCaption,const DocNodeList &children,
124124
const QCString &srcFile, int srcLine);
@@ -128,7 +128,7 @@ class DocbookDocVisitor : public DocVisitor
128128
const QCString &height, bool hasCaption,const DocNodeList &children,
129129
const QCString &srcFile, int srcLine);
130130
void endDotFile(bool hasCaption);
131-
void writeDotFile(const QCString &fileName, const DocVerbatim &s);
131+
void writeDotFile(const QCString &fileName, const DocVerbatim &s, bool newFile = true);
132132
void writePlantUMLFile(const QCString &fileName, const DocVerbatim &s);
133133
void startPlantUmlFile(const QCString &fileName,const QCString &relPath, const QCString &width,
134134
const QCString &height, bool hasCaption,const DocNodeList &children,

src/dot.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ void writeDotImageMapFromFile(TextStream &t,
284284
const QCString &inFile, const QCString &outDir,
285285
const QCString &relPath, const QCString &baseName,
286286
const QCString &context,int graphId,
287-
const QCString &srcFile,int srcLine)
287+
const QCString &srcFile,int srcLine, bool newFile)
288288
{
289289

290290
Dir d(outDir.str());
@@ -310,9 +310,12 @@ void writeDotImageMapFromFile(TextStream &t,
310310
{
311311
QCString svgName = outDir+"/"+baseName+".svg";
312312
DotFilePatcher::writeSVGFigureLink(t,relPath,baseName,svgName);
313-
DotFilePatcher patcher(svgName);
314-
patcher.addSVGConversion("",TRUE,context,TRUE,graphId);
315-
patcher.run();
313+
if (newFile)
314+
{
315+
DotFilePatcher patcher(svgName);
316+
patcher.addSVGConversion("",TRUE,context,TRUE,graphId);
317+
patcher.run();
318+
}
316319
}
317320
else // bitmap graphics
318321
{

src/dot.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ void writeDotImageMapFromFile(TextStream &t,
5656
const QCString &inFile, const QCString& outDir,
5757
const QCString &relPath,const QCString& baseName,
5858
const QCString &context,int graphId,
59-
const QCString &srcFile,int srcLine);
59+
const QCString &srcFile,int srcLine,bool newFile);
6060

6161
#endif

src/htmldocvisitor.cpp

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@
3939
#include "portable.h"
4040
#include "codefragment.h"
4141
#include "cite.h"
42+
#include "md5.h"
4243

43-
static int dotindex = 1;
44-
static std::mutex dotindex_mutex;
45-
static int mscindex = 1;
46-
static std::mutex mscindex_mutex;
44+
static StringVector dotindex;
45+
static std::mutex dotindex_mutex;
46+
static StringVector mscindex;
47+
static std::mutex mscindex_mutex;
4748

4849
static const int NUM_HTML_LIST_TYPES = 4;
4950
static const char g_types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};
@@ -614,30 +615,40 @@ void HtmlDocVisitor::operator()(const DocVerbatim &s)
614615

615616
case DocVerbatim::Dot:
616617
{
618+
forceEndParagraph(s);
619+
620+
QCString stext = s.text();
617621
QCString fileName(4096, QCString::ExplicitSize);
618622

619-
forceEndParagraph(s);
620-
{
621-
std::lock_guard<std::mutex> lock(dotindex_mutex);
622-
fileName.sprintf("%s%d%s",
623-
qPrint(Config_getString(HTML_OUTPUT)+"/inline_dotgraph_"),
624-
dotindex++,
625-
".dot"
626-
);
627-
}
628-
std::ofstream file = Portable::openOutputStream(fileName);
629-
if (!file.is_open())
623+
uint8_t md5_sig[16];
624+
char sigStr[33];
625+
MD5Buffer(stext.data(),static_cast<unsigned int>(stext.length()),md5_sig);
626+
MD5SigToString(md5_sig,sigStr);
627+
628+
fileName = Config_getString(HTML_OUTPUT) + "/inline_dotgraph_" + sigStr + ".dot";
629+
bool newFile = false;
630+
bool openError = false;
631+
std::lock_guard<std::mutex> lock(dotindex_mutex);
632+
if (std::find(dotindex.begin(), dotindex.end(), sigStr) == dotindex.end())
630633
{
631-
err("Could not open file {} for writing\n",fileName);
634+
newFile = true;
635+
dotindex.emplace_back(sigStr);
636+
std::ofstream file = Portable::openOutputStream(fileName);
637+
if (!file.is_open())
638+
{
639+
err("Could not open file {} for writing\n",fileName);
640+
openError = true;
641+
}
642+
else
643+
{
644+
file.write( stext.data(), stext.length() );
645+
file.close();
646+
}
632647
}
633-
else
648+
if (!openError)
634649
{
635-
QCString stext = s.text();
636-
file.write( stext.data(), stext.length() );
637-
file.close();
638-
639650
m_t << "<div class=\"dotgraph\">\n";
640-
writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
651+
writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine(),newFile);
641652
visitCaption(m_t, s);
642653
m_t << "</div>\n";
643654

@@ -650,31 +661,42 @@ void HtmlDocVisitor::operator()(const DocVerbatim &s)
650661
{
651662
forceEndParagraph(s);
652663

664+
QCString stext = s.text();
653665
QCString baseName(4096, QCString::ExplicitSize);
654666

667+
uint8_t md5_sig[16];
668+
char sigStr[33];
669+
MD5Buffer(stext.data(),static_cast<unsigned int>(stext.length()),md5_sig);
670+
MD5SigToString(md5_sig,sigStr);
671+
672+
baseName = Config_getString(HTML_OUTPUT) + "/inline_mscgraph_" + sigStr;
673+
bool newFile = false;
674+
bool openError = false;
675+
std::lock_guard<std::mutex> lock(mscindex_mutex);
676+
if (std::find(mscindex.begin(), mscindex.end(), sigStr) == mscindex.end())
655677
{
656-
std::lock_guard<std::mutex> lock(mscindex_mutex);
657-
baseName.sprintf("%s%d",
658-
qPrint(Config_getString(HTML_OUTPUT)+"/inline_mscgraph_"),
659-
mscindex++
660-
);
661-
}
662-
std::ofstream file = Portable::openOutputStream(baseName.str()+".msc");
663-
if (!file.is_open())
664-
{
665-
err("Could not open file {}.msc for writing\n",baseName);
678+
newFile = true;
679+
mscindex.emplace_back(sigStr);
680+
std::ofstream file = Portable::openOutputStream(baseName.str()+".msc");
681+
if (!file.is_open())
682+
{
683+
err("Could not open file {}.msc for writing\n",baseName);
684+
openError = true;
685+
}
686+
else
687+
{
688+
QCString text = "msc {";
689+
text+=s.text();
690+
text+="}";
691+
692+
file.write( text.data(), text.length() );
693+
file.close();
694+
}
666695
}
667-
else
696+
if (!openError)
668697
{
669-
QCString text = "msc {";
670-
text+=s.text();
671-
text+="}";
672-
673-
file.write( text.data(), text.length() );
674-
file.close();
675-
676698
m_t << "<div class=\"mscgraph\">\n";
677-
writeMscFile(baseName+".msc",s.relPath(),s.context(),s.srcFile(),s.srcLine());
699+
writeMscFile(baseName+".msc",s.relPath(),s.context(),s.srcFile(),s.srcLine(),newFile);
678700
visitCaption(m_t, s);
679701
m_t << "</div>\n";
680702

@@ -2215,17 +2237,17 @@ void HtmlDocVisitor::endLink()
22152237
}
22162238

22172239
void HtmlDocVisitor::writeDotFile(const QCString &fn,const QCString &relPath,
2218-
const QCString &context,const QCString &srcFile,int srcLine)
2240+
const QCString &context,const QCString &srcFile,int srcLine,bool newFile)
22192241
{
22202242
QCString baseName=makeBaseName(fn);
22212243
baseName.prepend("dot_");
22222244
QCString outDir = Config_getString(HTML_OUTPUT);
2223-
writeDotGraphFromFile(fn,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2224-
writeDotImageMapFromFile(m_t,fn,outDir,relPath,baseName,context,-1,srcFile,srcLine);
2245+
if (newFile) writeDotGraphFromFile(fn,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine);
2246+
writeDotImageMapFromFile(m_t,fn,outDir,relPath,baseName,context,-1,srcFile,srcLine,newFile);
22252247
}
22262248

22272249
void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,
2228-
const QCString &context,const QCString &srcFile,int srcLine)
2250+
const QCString &context,const QCString &srcFile,int srcLine, bool newFile)
22292251
{
22302252
QCString baseName=makeBaseName(fileName);
22312253
baseName.prepend("msc_");
@@ -2234,7 +2256,7 @@ void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPa
22342256
MscOutputFormat mscFormat = MscOutputFormat::BITMAP;
22352257
if ("svg" == imgExt)
22362258
mscFormat = MscOutputFormat::SVG;
2237-
writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
2259+
if (newFile) writeMscGraphFromFile(fileName,outDir,baseName,mscFormat,srcFile,srcLine);
22382260
writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context,mscFormat,srcFile,srcLine);
22392261
}
22402262

0 commit comments

Comments
 (0)