Skip to content

Commit 978d4b5

Browse files
committed
Create new temp file interface
New temporary file handling interface created. hthor changed to use the new interface. Signed-off-by: Dave Streeter <dave.streeter@lexisnexisrisk.com>
1 parent ecb9e5c commit 978d4b5

4 files changed

Lines changed: 240 additions & 180 deletions

File tree

ecl/eclagent/agentctx.hpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,14 @@ interface IOrderedOutputSerializer;
8080
typedef enum { ofSTD, ofXML, ofRAW } outputFmts;
8181
enum class AccessMode : unsigned;
8282

83-
struct IAgentContext : extends IGlobalCodeContext
83+
interface ITempFileHandler
84+
{
85+
virtual const char *noteTemporaryFile(const char * fname) = 0;
86+
virtual const char *queryTemporaryFile(const char * fname) = 0;
87+
virtual void removeTemporaryFile(const char * fname) = 0;
88+
};
89+
90+
struct IAgentContext : extends IGlobalCodeContext, extends ITempFileHandler
8491
{
8592
virtual void reportProgress(const char *msg, unsigned flags=0) = 0;
8693
virtual bool queryResolveFilesLocally() = 0;
@@ -92,12 +99,9 @@ struct IAgentContext : extends IGlobalCodeContext
9299

93100
virtual IConstWorkUnit *queryWorkUnit() const = 0;
94101
virtual IWorkUnit *updateWorkUnit() const = 0;
95-
102+
96103
virtual ILocalOrDistributedFile *resolveLFN(const char *logicalName, const char *errorTxt, bool optional, bool noteRead, AccessMode accessMode, StringBuffer * expandedlfn, bool isPrivilegedUser) = 0;
97104
virtual StringBuffer & getTempfileBase(StringBuffer & buff) = 0;
98-
virtual const char *noteTemporaryFile(const char *fname) = 0;
99-
virtual const char *noteTemporaryFilespec(const char *fname) = 0;
100-
virtual const char *queryTemporaryFile(const char *fname) = 0;
101105
virtual void reloadWorkUnit() = 0;
102106

103107
virtual char *resolveName(const char *in, char *out, unsigned outlen) = 0;
@@ -110,14 +114,14 @@ struct IAgentContext : extends IGlobalCodeContext
110114
virtual void outputFormattedResult(const char *name, unsigned sequence, bool close) = 0;
111115

112116
virtual const char *queryAllowedPipePrograms() = 0;
113-
117+
114118
virtual IOrderedOutputSerializer * queryOutputSerializer() = 0;
115119

116120
virtual IGroup *getHThorGroup(StringBuffer &grpnameout) = 0;
117121

118122
virtual RecordTranslationMode getLayoutTranslationMode() const = 0;
119123
virtual unsigned __int64 queryStopAfter() = 0;
120-
124+
121125
virtual const char *queryWuid() = 0;
122126

123127
virtual void updateWULogfile(IWorkUnit *outputWU) = 0;

ecl/eclagent/eclagent.cpp

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -615,46 +615,94 @@ StringBuffer & EclAgent::getTempfileBase(StringBuffer & buff)
615615
return buff.append(queryTempfilePath()).append(PATHSEPCHAR).appendLower(wuid);
616616
}
617617

618-
const char *EclAgent::queryTemporaryFile(const char *fname)
618+
const char *EclAgent::queryTemporaryFile(const char * fname)
619619
{
620-
StringBuffer tempfilename;
621-
getTempfileBase(tempfilename).append(PATHSEPCHAR).append(fname);
620+
dbgassertex(!isEmptyString(fname));
621+
622622
CriticalBlock crit(tfsect);
623-
ForEachItemIn(idx, tempFiles)
624-
{
625-
if (strcmp(tempFiles.item(idx), tempfilename.str())==0)
626-
return tempFiles.item(idx);
627-
}
623+
624+
Linked<CTempFileInfo> tempFileInfo = tempFileInfoMap.getValue(fname);
625+
if (tempFileInfo)
626+
return tempFileInfo->tempFileName.str();
627+
628628
StringBuffer errmsg;
629-
errmsg.append("Attempt to read temp file that has not yet been registered: ").append(tempfilename);
629+
errmsg.append("Attempt to read temp file that has not yet been registered: ").append(tempFileInfo->tempFileName.str());
630630
fail(0, errmsg.str());
631-
return 0;
631+
return nullptr;
632632
}
633633

634-
const char *EclAgent::noteTemporaryFile(const char *fname)
634+
const char *EclAgent::noteTemporaryFile(const char * fname)
635635
{
636-
StringBuffer tempfilename;
637-
getTempfileBase(tempfilename).append(PATHSEPCHAR).append(fname);
636+
if (isEmptyString(fname))
637+
{
638+
fail(0, "Attempt to register empty temp file name");
639+
return nullptr;
640+
}
641+
638642
CriticalBlock crit(tfsect);
639-
tempFiles.append(tempfilename.str());
640-
return tempFiles.item(tempFiles.length()-1);
643+
644+
Linked<CTempFileInfo> tempFileInfo = tempFileInfoMap.getValue(fname);
645+
if (tempFileInfo)
646+
{
647+
WARNLOG("Warning: temp file already registered %s", fname);
648+
return tempFileInfo->tempFileName.str();
649+
}
650+
651+
/* tempOwnerId is used at the end of the temporary file name to ensure
652+
* that in the event of a crash, we can use the pid and start time to
653+
* determine if temp files are from a currently running process or not,
654+
* and therefore whether they can be safely deleted.
655+
*/
656+
if (tempOwnerId.isEmpty())
657+
{
658+
unsigned pid = (unsigned)GetCurrentProcessId();
659+
unsigned __int64 startEpoch = (unsigned __int64)time(nullptr);
660+
tempOwnerId.append('.').append(pid).append('.').append(startEpoch);
661+
}
662+
663+
tempFileInfo.setown(new CTempFileInfo);
664+
tempFileInfoMap.setValue(fname, tempFileInfo.getLink());
665+
666+
StringBuffer base;
667+
getTempfileBase(base);
668+
base.append(PATHSEPCHAR);
669+
StringBuffer tail;
670+
splitFilename(fname, nullptr, nullptr, &tail, nullptr);
671+
tempFileInfo->tempFileName.append(base).append(tail).append(tempOwnerId);
672+
673+
return tempFileInfo->tempFileName.str();
641674
}
642675

643-
const char *EclAgent::noteTemporaryFilespec(const char *fspec)
676+
void EclAgent::removeTemporaryFile(const char * fname)
644677
{
645-
CriticalBlock crit(tfsect);
646-
tempFiles.append(fspec);
647-
return tempFiles.item(tempFiles.length()-1);
678+
dbgassertex(!isEmptyString(fname));
679+
680+
const char *tempFileName = queryTemporaryFile(fname);
681+
if (tempFileName)
682+
{
683+
Owned<IFile> file = createIFile(tempFileName);
684+
if (file->isFile() != fileBool::foundYes)
685+
return;
686+
687+
file->remove();
688+
}
648689
}
649690

650691
void EclAgent::deleteTempFiles()
651692
{
652693
CriticalBlock crit(tfsect);
653-
ForEachItemIn(idx, tempFiles)
694+
695+
if (!tempOwnerId.isEmpty())
654696
{
655-
remove(tempFiles.item(idx));
697+
HashIterator it(tempFileInfoMap);
698+
ForEach(it)
699+
{
700+
const char *originalId = static_cast<const char *>(it.query().getKey());
701+
CTempFileInfo *tempFileInfo = tempFileInfoMap.getValue(originalId);
702+
if (tempFileInfo)
703+
removeTemporaryFile(originalId);
704+
}
656705
}
657-
tempFiles.kill();
658706
}
659707

660708
const char *EclAgent::loadResource(unsigned id)

ecl/eclagent/eclagent.ipp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,17 @@ public:
172172
{
173173
return ctx->getTempfileBase(buff);
174174
}
175-
virtual const char *noteTemporaryFile(const char *fname)
175+
virtual const char *noteTemporaryFile(const char * fname)
176176
{
177177
return ctx->noteTemporaryFile(fname);
178178
}
179-
virtual const char *noteTemporaryFilespec(const char *fspec)
179+
virtual const char *queryTemporaryFile(const char * fname)
180180
{
181-
return ctx->noteTemporaryFilespec(fspec);
181+
return ctx->queryTemporaryFile(fname);
182182
}
183-
virtual const char *queryTemporaryFile(const char *fname)
183+
virtual void removeTemporaryFile(const char * fname)
184184
{
185-
return ctx->queryTemporaryFile(fname);
185+
ctx->removeTemporaryFile(fname);
186186
}
187187
virtual void reloadWorkUnit()
188188
{
@@ -357,6 +357,11 @@ class EclAgent : implements IAgentContext, implements ICodeContext, implements I
357357
private:
358358
friend class EclAgentWorkflowMachine;
359359

360+
struct CTempFileInfo : public CInterfaceOf<IInterface>
361+
{
362+
StringBuffer tempFileName;
363+
};
364+
360365
Owned<EclAgentWorkflowMachine> workflow;
361366
Owned<IConstWorkUnit> wuRead;
362367
Owned<roxiemem::IRowManager> rowManager;
@@ -378,7 +383,8 @@ private:
378383
outputFmts outputFmt = ofSTD;
379384
unsigned __int64 stopAfter;
380385
mutable CriticalSection wusect;
381-
StringArray tempFiles;
386+
MapStringToMyClass<CTempFileInfo> tempFileInfoMap; // Map of original temp file name to the actual temp file name on disk
387+
StringBuffer tempOwnerId; // Holds the current pid and start epoch of the process for temp files in map tempFileInfoMap
382388
CriticalSection tfsect;
383389
IArray persistReadLocks;
384390
StringArray processedPersists;
@@ -615,9 +621,9 @@ public:
615621

616622
virtual unsigned __int64 getDatasetHash(const char * name, unsigned __int64 hash);
617623
virtual void reportProgress(const char *msg, unsigned flags=0);
618-
virtual const char *noteTemporaryFile(const char *fname);
619-
virtual const char *noteTemporaryFilespec(const char *fspec);
620-
virtual const char *queryTemporaryFile(const char *fname);
624+
virtual const char *noteTemporaryFile(const char * fname);
625+
virtual const char *queryTemporaryFile(const char * fname);
626+
virtual void removeTemporaryFile(const char * fname);
621627
virtual void deleteFile(const char * logicalName);
622628

623629
void addException(ErrorSeverity severity, const char * source, unsigned code, const char * text, const char * filename, unsigned lineno, unsigned column, bool failOnError, bool isAbort);

0 commit comments

Comments
 (0)