Skip to content

Commit 4e029c2

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 4e029c2

4 files changed

Lines changed: 236 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: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -615,46 +615,90 @@ 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;
632631
}
633632

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

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

650687
void EclAgent::deleteTempFiles()
651688
{
652689
CriticalBlock crit(tfsect);
653-
ForEachItemIn(idx, tempFiles)
690+
691+
if (!tempOwnerId.isEmpty())
654692
{
655-
remove(tempFiles.item(idx));
693+
HashIterator it(tempFileInfoMap);
694+
ForEach(it)
695+
{
696+
const char *originalId = static_cast<const char *>(it.query().getKey());
697+
CTempFileInfo *tempFileInfo = tempFileInfoMap.getValue(originalId);
698+
if (tempFileInfo)
699+
removeTemporaryFile(originalId);
700+
}
656701
}
657-
tempFiles.kill();
658702
}
659703

660704
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)