|
@@ -817,8 +817,10 @@ public:
|
|
|
|
|
|
virtual bool isSink() const
|
|
virtual bool isSink() const
|
|
{
|
|
{
|
|
|
|
+ //If an internal result has as many dependencies (within the graph) as uses (which includes from outside the graph) then don't execute it unconditionally.
|
|
|
|
+ bool internalSpillAllUsesWithinGraph = (isInternal && dependentCount && dependentCount==usageCount);
|
|
//only a sink if a root activity
|
|
//only a sink if a root activity
|
|
- return isRoot && !(isInternal && dependentCount && dependentCount==usageCount); // MORE - it's possible for this to get the answer wrong still, since usageCount does not include references from main procedure. Gavin?
|
|
|
|
|
|
+ return isRoot && !internalSpillAllUsesWithinGraph;
|
|
}
|
|
}
|
|
|
|
|
|
virtual void getEdgeProgressInfo(unsigned idx, IPropertyTree &edge) const
|
|
virtual void getEdgeProgressInfo(unsigned idx, IPropertyTree &edge) const
|
|
@@ -1715,7 +1717,17 @@ public:
|
|
IFinalRoxieInput *saveInput = input;
|
|
IFinalRoxieInput *saveInput = input;
|
|
Owned<IStrandJunction> saveJunction = junction.getClear();
|
|
Owned<IStrandJunction> saveJunction = junction.getClear();
|
|
input = NULL; // Make sure parent does not start the chain yet
|
|
input = NULL; // Make sure parent does not start the chain yet
|
|
- CRoxieServerActivity::start(parentExtractSize, parentExtract, paused);
|
|
|
|
|
|
+ try
|
|
|
|
+ {
|
|
|
|
+ CRoxieServerActivity::start(parentExtractSize, parentExtract, paused);
|
|
|
|
+ }
|
|
|
|
+ catch (...)
|
|
|
|
+ {
|
|
|
|
+ // Make sure we restore these even if there is an exception thrown during start
|
|
|
|
+ input = saveInput;
|
|
|
|
+ junction.setown(saveJunction.getClear());
|
|
|
|
+ throw;
|
|
|
|
+ }
|
|
input = saveInput;
|
|
input = saveInput;
|
|
junction.setown(saveJunction.getClear());
|
|
junction.setown(saveJunction.getClear());
|
|
}
|
|
}
|
|
@@ -2088,7 +2100,16 @@ public:
|
|
{
|
|
{
|
|
IFinalRoxieInput *save = input;
|
|
IFinalRoxieInput *save = input;
|
|
input = NULL; // Make sure parent does not start the chain yet - but we do want to do the dependencies (because the decision about whether to start may depend on them)
|
|
input = NULL; // Make sure parent does not start the chain yet - but we do want to do the dependencies (because the decision about whether to start may depend on them)
|
|
- CRoxieServerActivity::start(parentExtractSize, parentExtract, paused);
|
|
|
|
|
|
+ try
|
|
|
|
+ {
|
|
|
|
+ CRoxieServerActivity::start(parentExtractSize, parentExtract, paused);
|
|
|
|
+ }
|
|
|
|
+ catch (...)
|
|
|
|
+ {
|
|
|
|
+ // Make sure we restore these even if there is an exception thrown during start
|
|
|
|
+ input = save;
|
|
|
|
+ throw;
|
|
|
|
+ }
|
|
input = save;
|
|
input = save;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2163,7 +2184,8 @@ protected:
|
|
IEngineRowStream *inputStream;
|
|
IEngineRowStream *inputStream;
|
|
IRecordPullerCallback *helper;
|
|
IRecordPullerCallback *helper;
|
|
Semaphore started; // MORE: GH->RKC I'm pretty sure this can be deleted, since handled by RestartableThread
|
|
Semaphore started; // MORE: GH->RKC I'm pretty sure this can be deleted, since handled by RestartableThread
|
|
- bool groupAtOnce, eof, eog;
|
|
|
|
|
|
+ bool groupAtOnce, eog;
|
|
|
|
+ std::atomic<bool> eof;
|
|
CriticalSection crit;
|
|
CriticalSection crit;
|
|
|
|
|
|
public:
|
|
public:
|
|
@@ -2256,6 +2278,7 @@ public:
|
|
CriticalBlock c(crit); // stop is called on our consumer's thread. We need to take care calling stop for our input to make sure it is not in mid-nextRow etc etc.
|
|
CriticalBlock c(crit); // stop is called on our consumer's thread. We need to take care calling stop for our input to make sure it is not in mid-nextRow etc etc.
|
|
if (inputStream)
|
|
if (inputStream)
|
|
inputStream->stop();
|
|
inputStream->stop();
|
|
|
|
+ eof = true;
|
|
}
|
|
}
|
|
RestartableThread::join();
|
|
RestartableThread::join();
|
|
}
|
|
}
|
|
@@ -2297,12 +2320,13 @@ public:
|
|
{
|
|
{
|
|
if (eof)
|
|
if (eof)
|
|
return false;
|
|
return false;
|
|
- while (preload)
|
|
|
|
|
|
+ while (preload && !eof)
|
|
{
|
|
{
|
|
- const void * row;
|
|
|
|
|
|
+ const void * row = nullptr;
|
|
{
|
|
{
|
|
CriticalBlock c(crit); // See comments in stop for why this is needed
|
|
CriticalBlock c(crit); // See comments in stop for why this is needed
|
|
- row = inputStream->nextRow();
|
|
|
|
|
|
+ if (!eof)
|
|
|
|
+ row = inputStream->nextRow();
|
|
}
|
|
}
|
|
if (row)
|
|
if (row)
|
|
{
|
|
{
|
|
@@ -2331,10 +2355,11 @@ public:
|
|
unsigned rowsDone = 0;
|
|
unsigned rowsDone = 0;
|
|
while (preload && !eof)
|
|
while (preload && !eof)
|
|
{
|
|
{
|
|
- const void *row;
|
|
|
|
|
|
+ const void *row = nullptr;
|
|
{
|
|
{
|
|
CriticalBlock c(crit);
|
|
CriticalBlock c(crit);
|
|
- row = inputStream->nextRow();
|
|
|
|
|
|
+ if (!eof)
|
|
|
|
+ row = inputStream->nextRow();
|
|
}
|
|
}
|
|
if (row)
|
|
if (row)
|
|
{
|
|
{
|
|
@@ -5296,6 +5321,17 @@ public:
|
|
{
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ //override execute() to ensure that start is nevr called on any input activities.
|
|
|
|
+ virtual void execute(unsigned parentExtractSize, const byte * parentExtract) override
|
|
|
|
+ {
|
|
|
|
+ CriticalBlock b(ecrit);
|
|
|
|
+ if (!executed)
|
|
|
|
+ {
|
|
|
|
+ executed = true;
|
|
|
|
+ stop();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
virtual void onExecute() override
|
|
virtual void onExecute() override
|
|
{
|
|
{
|
|
}
|
|
}
|
|
@@ -21630,6 +21666,7 @@ public:
|
|
class CRoxieServerWorkUnitWriteActivityFactory : public CRoxieServerInternalSinkFactory
|
|
class CRoxieServerWorkUnitWriteActivityFactory : public CRoxieServerInternalSinkFactory
|
|
{
|
|
{
|
|
bool isReread;
|
|
bool isReread;
|
|
|
|
+ bool isUnused = false;
|
|
|
|
|
|
public:
|
|
public:
|
|
CRoxieServerWorkUnitWriteActivityFactory(unsigned _id, unsigned _subgraphId, IQueryFactory &_queryFactory, HelperFactory *_helperFactory, ThorActivityKind _kind, IPropertyTree &_graphNode, unsigned _usageCount, bool _isRoot)
|
|
CRoxieServerWorkUnitWriteActivityFactory(unsigned _id, unsigned _subgraphId, IQueryFactory &_queryFactory, HelperFactory *_helperFactory, ThorActivityKind _kind, IPropertyTree &_graphNode, unsigned _usageCount, bool _isRoot)
|
|
@@ -21638,13 +21675,27 @@ public:
|
|
isReread = usageCount > 0;
|
|
isReread = usageCount > 0;
|
|
Owned<IHThorWorkUnitWriteArg> helper = (IHThorWorkUnitWriteArg *) helperFactory();
|
|
Owned<IHThorWorkUnitWriteArg> helper = (IHThorWorkUnitWriteArg *) helperFactory();
|
|
isInternal = (helper->getSequence()==ResultSequenceInternal);
|
|
isInternal = (helper->getSequence()==ResultSequenceInternal);
|
|
|
|
+ isUnused = isInternal && (usageCount == 0);
|
|
}
|
|
}
|
|
|
|
|
|
virtual IRoxieServerActivity *createActivity(IRoxieAgentContext *_ctx, IProbeManager *_probeManager) const
|
|
virtual IRoxieServerActivity *createActivity(IRoxieAgentContext *_ctx, IProbeManager *_probeManager) const
|
|
{
|
|
{
|
|
|
|
+ if (isUnused && !CRoxieServerInternalSinkFactory::isSink())
|
|
|
|
+ {
|
|
|
|
+ if (_ctx->queryTraceLevel() > 2)
|
|
|
|
+ DBGLOG("Workunit write %u is unused - create null activity", id);
|
|
|
|
+ //Create a null sink activity that is always executed to ensure that stop() is called on the input.
|
|
|
|
+ return createRoxieServerNullSinkActivity(_ctx, this, _probeManager);
|
|
|
|
+ }
|
|
|
|
+
|
|
return new CRoxieServerWorkUnitWriteActivity(_ctx, this, _probeManager, isReread, usageCount);
|
|
return new CRoxieServerWorkUnitWriteActivity(_ctx, this, _probeManager, isReread, usageCount);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ virtual bool isSink() const
|
|
|
|
+ {
|
|
|
|
+ return isUnused || CRoxieServerInternalSinkFactory::isSink();
|
|
|
|
+ }
|
|
|
|
+
|
|
};
|
|
};
|
|
|
|
|
|
IRoxieServerActivityFactory *createRoxieServerWorkUnitWriteActivityFactory(unsigned _id, unsigned _subgraphId, IQueryFactory &_queryFactory, HelperFactory *_helperFactory, ThorActivityKind _kind, IPropertyTree &_graphNode, unsigned _usageCount, bool _isRoot)
|
|
IRoxieServerActivityFactory *createRoxieServerWorkUnitWriteActivityFactory(unsigned _id, unsigned _subgraphId, IQueryFactory &_queryFactory, HelperFactory *_helperFactory, ThorActivityKind _kind, IPropertyTree &_graphNode, unsigned _usageCount, bool _isRoot)
|