Job-Planning: dispose of FrameCoord in pipeline and Dispatcher interface

...as a preparation for solving a logical problem with the Planning-Pipeline;
it can not quite work as intended just by passing down the pair of
current ticket and dependent ticket, since we have to calculate a chained
calculation of job deadlines, leading up to the root ticket for a frame.

My solution idea is to create the JobPlanning earlier in the pipeline,
already *before* the expansion of prerequisites, and rather to integrate
the representation of the dependency relation direcly into JobPlanning
This commit is contained in:
Fischlurch 2023-06-18 03:50:48 +02:00
parent 661d768fad
commit a1c1456849
16 changed files with 404 additions and 76 deletions

View file

@ -36,6 +36,7 @@
namespace steam {
namespace engine {
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
/** */
FrameCoord
DispatchTable::locateRelative (FrameCoord const&, FrameCnt frameOffset)
@ -48,9 +49,10 @@ namespace engine {
{
UNIMPLEMENTED ("determine when to finish a planning chunk");
}
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
JobTicket&
DispatchTable::accessJobTicket (size_t, TimeValue nominalTime)
DispatchTable::getJobTicketFor (size_t, TimeValue nominalTime)
{
UNIMPLEMENTED ("hook into the real implementation of the model backbone / segmentation");
}

View file

@ -53,10 +53,12 @@ namespace engine {
/* ==== Dispatcher interface ==== */
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
FrameCoord locateRelative (FrameCoord const&, FrameCnt frameOffset) override;
bool isEndOfChunk (FrameCnt, ModelPort port) override;
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
size_t resolveModelPort (ModelPort) override;
JobTicket& accessJobTicket (size_t, TimeValue nominalTime) override;
JobTicket& getJobTicketFor (size_t, TimeValue nominalTime) override;
protected:
/** timerange covered by this RenderGraph */

View file

@ -37,7 +37,6 @@ namespace steam {
namespace engine {
Dispatcher::~Dispatcher() { } // emit VTables and Typeinfo here....
FrameSequencer::~FrameSequencer() { }
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...

View file

@ -45,7 +45,7 @@
#include "steam/play/output-slot.hpp"
#include "lib/iter-tree-explorer.hpp"
#include "lib/time/timevalue.hpp"
//#include "lib/nocopy.hpp"
#include "lib/nocopy.hpp"
#include <functional>
#include <utility>
@ -89,7 +89,7 @@ namespace engine {
* @todo 6/23 API is remoulded from ground up (»Playback Vertical Slice« integration effort)
*/
class Dispatcher
: public FrameLocator
: util::NonCopyable
{
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
@ -162,7 +162,6 @@ namespace engine {
virtual size_t resolveModelPort (ModelPort) =0;
protected:
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
/** core dispatcher operation: based on the coordinates of a reference point,
* establish binding frame number, nominal time and real (wall clock) deadline.
@ -192,7 +191,16 @@ namespace engine {
//////////// - but this leads to a lot of duplicated Timings records, unless we rewrite the TimeAnchor to be noncopyable and use a Timings const&
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
virtual JobTicket& accessJobTicket (size_t, TimeValue nominalTime) =0;
/**
* Core Dispatcher operation: locate the appropriate Segment and
* retrieve/derive a »blueprint« for render job generation.
* @param portIDX index-number for a ModelPort [as resolved](\ref #resolveModelPort)
* @param nominalTime time of the frame to calculate, relative to Timeline origin
*/
virtual JobTicket& getJobTicketFor (size_t portIDX, TimeValue nominalTime) =0;
/** Convenience shortcut for tests: JobTicket ⟼ Job */
Job createJobFor (size_t portIDX, TimeValue nominalTime);
};
@ -289,9 +297,8 @@ namespace engine {
SRC::transform(
[portIDX](PipeFrameTick& core) -> TicketDepend
{
FrameCoord frame{core.currPoint, core.frameNr, portIDX};
return {nullptr
,& core.dispatcher->getJobTicketFor(frame)
,& core.dispatcher->getJobTicketFor(portIDX, core.currPoint)
};
}));
}
@ -364,12 +371,17 @@ namespace engine {
inline Dispatcher::PipelineBuilder<Dispatcher::PipeFrameTick>
Dispatcher::forCalcStream(Timings timings)
Dispatcher::forCalcStream (Timings timings)
{
return PipelineBuilder<PipeFrameTick> {this, timings};
}
inline Job
Dispatcher::createJobFor (size_t portIDX, TimeValue nominalTime)
{
return getJobTicketFor (portIDX, nominalTime)
.createJobFor (Time{nominalTime});
}

View file

@ -98,6 +98,7 @@ namespace engine {
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
/**
* Facility for producing a sequence of FrameCoord.
* This interface describes the essence of generating
@ -124,6 +125,7 @@ namespace engine {
protected:
virtual FrameCoord locateRelative (FrameCoord const&, FrameCnt frameOffset) =0;
};
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline

View file

@ -112,7 +112,7 @@ namespace engine {
Job
buildJob()
{
Job job = jobTicket_.createJobFor (frameCoord_);
Job job = jobTicket_.createJobFor (frameCoord_.absoluteNominalTime);
//////////////////////////////////////////////////////TICKET #1295 : somehow package and communicate the DataSink info
return job;
}
@ -312,6 +312,7 @@ namespace engine {
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
/**
* Abstraction: a Facility to establish frame coordinates
* and identify and access the execution plan for this frame.
@ -340,6 +341,7 @@ namespace engine {
virtual JobTicket& accessJobTicket (size_t, TimeValue nominalTime) =0;
virtual bool isEndOfChunk (FrameCnt, ModelPort port) =0;
};
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline

View file

@ -75,9 +75,8 @@ namespace engine {
* after the last Builder run created this part of the render network.
*/
Job
JobTicket::createJobFor (FrameCoord coordinates)
JobTicket::createJobFor (Time nominalTime)
{
Time nominalTime = coordinates.absoluteNominalTime;
if (this->empty())
{ //////////////////////////////////////////////////////////////////////////////////TICKET #1296 : can we get away just with a do-nothing functor?
return Job(nopFunctor(), InvocationInstanceID(), nominalTime);

View file

@ -142,7 +142,7 @@ using lib::LUID;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
Job createJobFor (FrameCoord coordinates);
Job createJobFor (Time nominalTime);
Duration getExpectedRuntime();

View file

@ -85,6 +85,7 @@ namespace test {
/* == mock Dispatcher implementation == */
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
FrameCoord
locateRelative (FrameCoord const&, FrameCnt frameOffset) override
{
@ -96,6 +97,7 @@ namespace test {
{
UNIMPLEMENTED ("determine when to finish a planning chunk");
}
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
size_t
resolveModelPort (ModelPort modelPort) override
@ -104,7 +106,7 @@ namespace test {
}
JobTicket&
accessJobTicket (size_t, TimeValue nominalTime) override
getJobTicketFor (size_t, TimeValue nominalTime) override
{
UNIMPLEMENTED ("dummy implementation of the model backbone / segmentation");
}

View file

@ -132,9 +132,8 @@ namespace test {
JobTicket& ticket = seg.jobTicket(0); // get the master-JobTicket from this segment
JobTicket& prereq = *(ticket.getPrerequisites()); // pull a prerequisite JobTicket
FrameCoord coord; // Frame coordinates for invocation (placeholder)
Job jobP = prereq.createJobFor(coord); // create an instance of the prerequisites for this coordinates
Job jobM = ticket.createJobFor(coord); // ...and an instance of the master job for the same coordinates
Job jobP = prereq.createJobFor(Time{0,15}); // create an instance of the prerequisites for some time(irrelevant)
Job jobM = ticket.createJobFor(Time{0,15}); // ...and an instance of the master job for the same time
CHECK (MockJobTicket::isAssociated (jobP, prereq));
CHECK (MockJobTicket::isAssociated (jobM, ticket));
CHECK (not MockJobTicket::isAssociated (jobP, ticket));
@ -146,11 +145,9 @@ namespace test {
CHECK (555 == MockJob::invocationAdditionalKey (jobP)); // indicating that in practice it will activate the proper render node
// (3) demonstrate mocked frame dispatcher...
coord.modelPortIDX = 1;
coord.absoluteNominalTime = Time{0,30};
MockDispatcher dispatcher; // a complete dispatcher backed by a mock Segment for the whole timeline
auto [port1,sink1] = dispatcher.getDummyConnection(1); // also some fake ModelPort and DataSink entries are registered
Job jobD = dispatcher.getJobTicketFor(coord).createJobFor(coord);
Job jobD = dispatcher.createJobFor (1, Time{0,30});
CHECK (dispatcher.verify(jobD, port1, sink1)); // the generated job uses the associated ModelPort and DataSink and JobTicket
}
@ -204,11 +201,10 @@ namespace test {
.pullFrom (port);
CHECK (not isnil (pipeline));
CHECK (nullptr == pipeline->first); // is a top-level ticket
CHECK (nullptr == pipeline->first); // is a top-level ticket
JobTicket& ticket = *pipeline->second;
FrameCoord dummy{Time::ZERO}; // actual time point is irrelevant here
Job job = ticket.createJobFor(dummy);
Job job = ticket.createJobFor(Time::ZERO); // actual time point is irrelevant here
CHECK (dispatcher.verify(job, port, sink));
}
@ -244,12 +240,12 @@ namespace test {
// the first element is identical to previous test
CHECK (not isnil (pipeline));
CHECK (nullptr == pipeline->first);
Job job = pipeline->second->createJobFor(FrameCoord{});
Job job = pipeline->second->createJobFor (Time::ZERO);
CHECK (11 == job.parameter.invoKey.part.a);
auto visualise = [](auto& pipeline) -> string
{
FrameCoord frame{pipeline.currPoint}; // can access the embedded PipeFrameTick core to get "currPoint" (nominal time)
Time frame{pipeline.currPoint}; // can access the embedded PipeFrameTick core to get "currPoint" (nominal time)
Job job = pipeline->second->createJobFor(frame); // looking always at the second element, which is the current JobTicket
TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (gavl_time_t)
int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here

View file

@ -114,9 +114,9 @@ namespace test {
Time nominalTime{200,0};
size_t portIDX = dispatcher.resolveModelPort (port);
FrameCoord frame{nominalTime, portIDX};
JobTicket& ticket = dispatcher.getJobTicketFor(frame);
JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
FrameCoord frame{nominalTime, portIDX}; /////////////////////////////OOO replace FrameCoord
JobPlanning plan{frame,ticket,sink};
Job job = plan.buildJob();
@ -138,9 +138,9 @@ namespace test {
FrameCnt frameNr{5};
Time nominalTime{200,0};
size_t portIDX = dispatcher.resolveModelPort (port);
FrameCoord frame{nominalTime, frameNr, portIDX};
JobTicket& ticket = dispatcher.getJobTicketFor(frame);
JobTicket& ticket = dispatcher.getJobTicketFor(portIDX, nominalTime);
FrameCoord frame{nominalTime, frameNr, portIDX}; /////////////////////////////OOO replace FrameCoord
JobPlanning plan{frame,ticket,sink};
// the following calculations are expected to happen....

View file

@ -340,7 +340,7 @@ namespace test {
public:
/* == mock implementation of the Dispatcher interface == */
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
FrameCoord
locateRelative (FrameCoord const&, FrameCnt frameOffset) override
{
@ -352,7 +352,7 @@ namespace test {
{
UNIMPLEMENTED ("determine when to finish a planning chunk");
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsoleted by rework of Dispatcher-Pipeline
size_t
resolveModelPort (ModelPort modelPort) override
@ -366,7 +366,7 @@ namespace test {
JobTicket&
accessJobTicket (size_t portIDX, TimeValue nominalTime) override
getJobTicketFor (size_t portIDX, TimeValue nominalTime) override
{
auto& seg = mockSeg_[nominalTime];
return seg.jobTicket(portIDX);
@ -422,7 +422,7 @@ namespace test {
TimeValue nominalTime{job.parameter.nominalTime};
size_t portIDX = resolveModelPort (port);
JobTicket& ticket = accessJobTicket (portIDX, nominalTime);
JobTicket& ticket = getJobTicketFor (portIDX, nominalTime);
return isnil (ticket)? MockJob::isNopJob (job)
: MockJobTicket::isAssociated (job, ticket);
}

View file

@ -88,8 +88,7 @@ namespace test {
JobTicket& ticket = seg.jobTicket(0);
FrameCoord coord{Time(0,15)};
Job job = ticket.createJobFor(coord);
Job job = ticket.createJobFor (Time{0,15});
CHECK (MockJobTicket::isAssociated (job, ticket));
job.triggerJob();
@ -127,19 +126,19 @@ namespace test {
void
verify_MockJobTicket()
{
FrameCoord coord{lib::test::randTime()};
auto frameTime = lib::test::randTime();
// build a render job to do nothing....
Job nopJob = JobTicket::NOP.createJobFor(coord);
Job nopJob = JobTicket::NOP.createJobFor (frameTime);
CHECK (INSTANCEOF (vault::engine::NopJobFunctor, static_cast<JobClosure*> (nopJob.jobClosure))); //////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs)
CHECK (nopJob.parameter.nominalTime == coord.absoluteNominalTime);
CHECK (nopJob.parameter.nominalTime == frameTime);
InvocationInstanceID empty; ///////////////////////////////////////////////////////////////////////TICKET #1287 : temporary workaround until we get rid of the C base structs
CHECK (lumiera_invokey_eq (&nopJob.parameter.invoKey, &empty));
CHECK (MockJob::isNopJob(nopJob)); // this diagnostic helper checks the same conditions as done here explicitly
MockJobTicket mockTicket;
CHECK (not mockTicket.empty());
Job mockJob = mockTicket.createJobFor (coord);
Job mockJob = mockTicket.createJobFor (frameTime);
CHECK ( mockTicket.verify_associated (mockJob)); // proof by invocation hash : is indeed backed by this JobTicket
CHECK (not mockTicket.verify_associated (nopJob)); // ...while some random other job is not related
CHECK (not MockJob::isNopJob(mockJob));
@ -159,7 +158,6 @@ namespace test {
verify_MockSegmentation()
{
Time someTime = lib::test::randTime();
FrameCoord coord{someTime};
//
//-----------------------------------------------------------------/// Empty default Segmentation
{
@ -177,8 +175,8 @@ namespace test {
JobTicket& ticket = mockSegs[someTime].jobTicket(0);
CHECK (not util::isSameObject (ticket, JobTicket::NOP));
Job someJob = ticket.createJobFor(coord); // JobTicket uses, but does not check the time given in FrameCoord
CHECK (someJob.parameter.nominalTime == _raw(coord.absoluteNominalTime));
Job someJob = ticket.createJobFor(someTime); // JobTicket uses, but does not check the time given
CHECK (someJob.parameter.nominalTime == someTime);
CHECK (MockJobTicket::isAssociated (someJob, ticket)); // but the generated Job is linked to the Closure backed by the JobTicket
CHECK (not MockJob::was_invoked (someJob));
@ -206,7 +204,7 @@ namespace test {
CHECK ( util::isSameObject (seg1.jobTicket(0),JobTicket::NOP));
CHECK (not util::isSameObject (seg2.jobTicket(0),JobTicket::NOP));// this one is the active segment
Job job = seg2.jobTicket(0).createJobFor(coord);
Job job = seg2.jobTicket(0).createJobFor(someTime);
CHECK (not MockJobTicket::isAssociated (job, seg1.jobTicket(0)));
CHECK ( MockJobTicket::isAssociated (job, seg2.jobTicket(0)));
CHECK (marker == job.parameter.invoKey.part.a);
@ -217,7 +215,7 @@ namespace test {
CHECK (marker == MockJob::invocationAdditionalKey (job)); // DummyClosure is rigged such as to feed back the seed in `part.a`
// and thus we can prove this job really belongs to the marked segment
// create another job from the (empty) seg1
job = seg1.jobTicket(0).createJobFor (coord);
job = seg1.jobTicket(0).createJobFor (someTime);
InvocationInstanceID empty; /////////////////////////////////////////////////////////////////////TICKET #1287 : temporary workaround until we get rid of the C base structs
CHECK (lumiera_invokey_eq (&job.parameter.invoKey, &empty)); // indicates that it's just a placeholder to mark a "NOP"-Job
CHECK (seg1.jobTicket(0).empty());
@ -246,7 +244,7 @@ namespace test {
CHECK (Time(0,20) == s3.start());
CHECK (Time::MAX == s3.after());
Job job = s2.jobTicket(0).createJobFor(coord);
Job job = s2.jobTicket(0).createJobFor(someTime);
job.triggerJob();
CHECK (marker == MockJob::invocationAdditionalKey (job));
}
@ -289,7 +287,7 @@ namespace test {
{
if (segment.empty()) return 0;
Job job = segment.jobTicket(0).createJobFor(coord);
Job job = segment.jobTicket(0).createJobFor(someTime);
job.triggerJob();
CHECK (MockJob::was_invoked (job));
CHECK (RealClock::wasRecently (MockJob::invocationTime (job)));
@ -314,7 +312,7 @@ namespace test {
void
verify_MockPrerequisites()
{
FrameCoord coord;
Time someTime = lib::test::randTime();
//-----------------------------------------------------------------/// one Segment with one additional prerequisite
{
MockSegmentation mockSegs{MakeRec()
@ -332,8 +330,8 @@ namespace test {
++prereq;
CHECK (isnil (prereq));
Job job1 = preTicket.createJobFor (coord);
Job job2 = ticket.createJobFor (coord);
Job job1 = preTicket.createJobFor (someTime);
Job job2 = ticket.createJobFor (someTime);
job1.triggerJob();
job2.triggerJob();
@ -369,7 +367,7 @@ namespace test {
.expandAll()
.transform ([&](JobTicket& ticket)
{
return ticket.createJobFor(coord).parameter.invoKey.part.a;
return ticket.createJobFor(someTime).parameter.invoKey.part.a;
});
@ -391,7 +389,6 @@ namespace test {
void
verify_MockDispatcherSetup()
{
FrameCoord frame{Time{0,30}};
{
MockDispatcher dispatcher;
// automatically generates some fake connection points...
@ -409,10 +406,11 @@ namespace test {
CHECK (0 == dispatcher.resolveModelPort(port0));
CHECK (1 == dispatcher.resolveModelPort(port1));
frame.modelPortIDX = 0;
Job job0 = dispatcher.getJobTicketFor(frame).createJobFor(frame);
frame.modelPortIDX = 1;
Job job1 = dispatcher.getJobTicketFor(frame).createJobFor(frame);
Time frameTime{0,30};
size_t modelPortIDX = 0;
Job job0 = dispatcher.createJobFor (modelPortIDX, frameTime);
modelPortIDX = 1;
Job job1 = dispatcher.createJobFor (modelPortIDX, frameTime);
CHECK (dispatcher.verify(job0, port0, sink0));
CHECK (dispatcher.verify(job1, port1, sink1));
}
@ -426,11 +424,9 @@ namespace test {
.attrib("start", Time{0,10}) // second segment covers 10s … +Time::MAX
.genNode()};
frame.modelPortIDX = 1;
frame.absoluteNominalTime = Time{0,5};
Job job0 = dispatcher.getJobTicketFor(frame).createJobFor(frame);
frame.absoluteNominalTime = Time{0,25};
Job job1 = dispatcher.getJobTicketFor(frame).createJobFor(frame);
size_t modelPortIDX = 1;
Job job0 = dispatcher.createJobFor (modelPortIDX, Time{0,5});
Job job1 = dispatcher.createJobFor (modelPortIDX, Time{0,25});
CHECK (11 == job0.parameter.invoKey.part.a);
CHECK (22 == job1.parameter.invoKey.part.a);

View file

@ -110,8 +110,7 @@ namespace test {
// verify mapped JobTicket is assembled according to above spec...
auto getMarker = [](JobTicket& ticket)
{
engine::FrameCoord dummyFrame;
Job job = ticket.createJobFor(dummyFrame);
Job job = ticket.createJobFor(Time::ANYTIME);
return job.parameter.invoKey.part.a;
};

View file

@ -101,8 +101,8 @@ namespace test{
virtual void
run (Arg)
{
ulong l1 (rand() % 1000);
ulong l2 (rand() % 1000);
ulong l1 (1 + rand() % 1000);
ulong l2 (1 + rand() % 1000);
string s1 (randStr(50));
string s2 (randStr(50));
const char* cp (s1.c_str());

View file

@ -64955,7 +64955,7 @@
</node>
<node CREATED="1685057613713" ID="ID_1402118663" MODIFIED="1685057622892" TEXT="&#xf6;ffnen / Belegen einer Output-Verbindung">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685057626464" ID="ID_106757636" MODIFIED="1685057709903" TEXT="Anpassung notwendig: Match auf ModelPort">
<linktarget COLOR="#fb1160" DESTINATION="ID_106757636" ENDARROW="Default" ENDINCLINATION="-78;630;" ID="Arrow_ID_1247503914" SOURCE="ID_1172676625" STARTARROW="None" STARTINCLINATION="1444;-44;"/>
<linktarget COLOR="#fb1160" DESTINATION="ID_106757636" ENDARROW="Default" ENDINCLINATION="-78;630;" ID="Arrow_ID_1247503914" SOURCE="ID_1172676625" STARTARROW="None" STARTINCLINATION="1533;-30;"/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
@ -70013,7 +70013,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
<icon BUILTIN="help"/>
<node CREATED="1686878263958" ID="ID_1822381853" MODIFIED="1686878292683" TEXT="jetzt brauch ich die Frame-Nr doch noch!">
<node CREATED="1686878263958" ID="ID_1822381853" LINK="#ID_1008817240" MODIFIED="1686878292683" TEXT="jetzt brauch ich die Frame-Nr doch noch!">
<richcontent TYPE="NOTE"><html>
<head>
@ -70026,6 +70026,40 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
<icon BUILTIN="stop-sign"/>
</node>
<node CREATED="1687044034446" ID="ID_1197569659" LINK="#ID_1471106329" MODIFIED="1687044160985" TEXT="werden jetzt die Arbeitsdaten des Tick-Generators">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...damit k&#246;nnten die FrameCoord ihre Bestimmung gefunden haben, denn in diesem Bezug sind auch FrameNr und nominalTime <i>nicht redundant (Quantisierung!)</i>, sondern machen die Grid-Anwendung explizit
</p>
</body>
</html></richcontent>
<icon BUILTIN="stop-sign"/>
</node>
<node CREATED="1687047345857" ID="ID_875727046" MODIFIED="1687047359796" TEXT="nein .. ja .. oh">
<icon BUILTIN="smiley-angry"/>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1687047257837" ID="ID_354859977" MODIFIED="1687047467443" TEXT="FrameCoord sind inzwischen ein sinnloses Konstrukt">
<linktarget COLOR="#9f154b" DESTINATION="ID_354859977" ENDARROW="Default" ENDINCLINATION="867;47;" ID="Arrow_ID_715252746" SOURCE="ID_965148273" STARTARROW="None" STARTINCLINATION="-226;-425;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1687047415820" ID="ID_450940415" MODIFIED="1687047453090">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<u>Fazit</u>: haben keine Rolle mehr und werden <b>aufgegeben</b>
</p>
</body>
</html></richcontent>
<icon BUILTIN="forward"/>
</node>
</node>
<node CREATED="1681169265752" ID="ID_388188594" MODIFIED="1681169268100" TEXT="JobTicket">
@ -75722,9 +75756,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793412168" ID="ID_566542363" MODIFIED="1686793437280" TEXT="Deadline festsetzen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793444999" ID="ID_890638508" MODIFIED="1686793453060" TEXT="einfacher Job">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686873856076" ID="ID_1099231430" MODIFIED="1686874375053" TEXT="eigentlich liegt das Wissen dar&#xfc;ber im JobFunktor">
<node COLOR="#338800" CREATED="1686793444999" ID="ID_890638508" MODIFIED="1686964333735" TEXT="einfacher Job">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1686873856076" ID="ID_1099231430" MODIFIED="1686964330736" TEXT="eigentlich liegt das Wissen dar&#xfc;ber im JobFunktor">
<arrowlink COLOR="#a56c6d" DESTINATION="ID_1464401657" ENDARROW="Default" ENDINCLINATION="-74;-579;" ID="Arrow_ID_1368232066" STARTARROW="None" STARTINCLINATION="933;50;"/>
<icon BUILTIN="idea"/>
<node COLOR="#338800" CREATED="1686874175948" HGAP="50" ID="ID_525505445" MODIFIED="1686878346429" TEXT="vorl&#xe4;ufige Fake-Info vorsehen" VSHIFT="-3">
@ -75737,7 +75771,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686874081293" ID="ID_1358950308" MODIFIED="1686874160334" TEXT="Zugriff sollte aber &#xfc;ber das JobTIcket-API gef&#xfc;hrt werden">
<node COLOR="#435e98" CREATED="1686874081293" ID="ID_1358950308" MODIFIED="1686964328409" TEXT="Zugriff sollte aber &#xfc;ber das JobTicket-API gef&#xfc;hrt werden">
<richcontent TYPE="NOTE"><html>
<head>
@ -75751,17 +75785,22 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
</node>
<node COLOR="#338800" CREATED="1686874427511" ID="ID_109124269" MODIFIED="1686878357594" TEXT="die bisher in TimeAnchor gecodete Logik hierher verschieben">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686875298675" ID="ID_981450024" MODIFIED="1686875356324" TEXT="Logik der Berechnung ausarbeiten">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1686875298675" ID="ID_981450024" MODIFIED="1686964324302" TEXT="Logik der Berechnung ausarbeiten">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1686878372095" ID="ID_735392622" MODIFIED="1686878381499" TEXT="Gesamt-Latenz">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1686878360841" ID="ID_26327492" MODIFIED="1686879600114" TEXT="f&#xfc;r Deadline eigentlich nur bei TIMEBOUND">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#435e98" CREATED="1686964484692" ID="ID_833129888" MODIFIED="1686964599342" TEXT="Rechenweg">
<icon BUILTIN="info"/>
<node CREATED="1686964521084" ID="ID_1952042504" MODIFIED="1686964541624" TEXT="Wall-Clock-Anchor-Punkt f&#xfc;r Grid-Origin"/>
<node CREATED="1686964542236" ID="ID_633743901" MODIFIED="1686964571926" TEXT="nominellen Offest dahinter &#x27fc; required time of arrival"/>
<node CREATED="1686964573870" ID="ID_1589778051" MODIFIED="1686964595226" TEXT="um die Gesamt-Latenz davor &#x27fc; Deadline"/>
</node>
<node COLOR="#435e98" CREATED="1686879601311" ID="ID_1446511354" MODIFIED="1686963909785" TEXT="Frage: wo wird nun der Anker zur wall-clock-Time etabliert?">
<icon BUILTIN="help"/>
<node CREATED="1686963864527" ID="ID_1675965203" MODIFIED="1686963907132" TEXT="liegt nun in den Timings">
@ -75778,6 +75817,284 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793449011" ID="ID_1790599874" MODIFIED="1686793453060" TEXT="abh&#xe4;ngiger Job">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686964367620" ID="ID_673983932" MODIFIED="1686964434017" TEXT="braucht Deadline des unmittelbar abh&#xe4;ngigen Nachfolger-Jobs">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686964642887" ID="ID_1372706833" MODIFIED="1686964706541" TEXT="verwende diese anstelle der erwarteten real-Grid-Time">
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1686965001287" ID="ID_1948616906" MODIFIED="1686965057296">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<u>Problem</u>&#160;: habe nur <b>JobTicket</b>&#160;des <i>unmittelbaren</i>&#160; Vorg&#228;ngers
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1686965066686" ID="ID_419807071" MODIFIED="1686965089388" TEXT="w&#xfc;rde aber die ganze Kette der JobPlannings bis zum Root-Job brauchen">
<icon BUILTIN="info"/>
</node>
<node CREATED="1686965163417" ID="ID_1358303460" MODIFIED="1686965216709" TEXT="eine Deadline ist Ergebnis einer Integration">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1686965322397" ID="ID_966792976" MODIFIED="1686965331679" TEXT="das JobTIcket kann die gar nicht errechnen"/>
<node CREATED="1686965332609" ID="ID_1561329377" MODIFIED="1686965353628" TEXT="Rechnung w&#xe4;re rekursiv, quadratisch"/>
<node CREATED="1686965354284" ID="ID_172681606" MODIFIED="1687039516255" TEXT="oder erfordert &#xbb;schleppenden&#xab; Zustand">
<arrowlink COLOR="#8e5572" DESTINATION="ID_1929351072" ENDARROW="Default" ENDINCLINATION="28;-47;" ID="Arrow_ID_753643955" STARTARROW="None" STARTINCLINATION="-70;5;"/>
</node>
</node>
<node CREATED="1687039335006" ID="ID_1929351072" MODIFIED="1687039516255" TEXT="&#xbb;schleppender Zustand&#xab;">
<linktarget COLOR="#8e5572" DESTINATION="ID_1929351072" ENDARROW="Default" ENDINCLINATION="28;-47;" ID="Arrow_ID_753643955" SOURCE="ID_172681606" STARTARROW="None" STARTINCLINATION="-70;5;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
<node CREATED="1687039436665" ID="ID_510256966" MODIFIED="1687039436665" TEXT="mu&#xdf; f&#xfc;r Job-Planning-Berechnung zug&#xe4;nglich sein"/>
<node CREATED="1687039484904" ID="ID_846229350" MODIFIED="1687039649451" TEXT="mu&#xdf; aber in der Expander-Funktion bereits vorliegen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
weil das die einzige Stelle ist in der zugleich Dependent und Dependency zug&#228;nglich sind
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1687039664958" ID="ID_1390938163" MODIFIED="1687039709039" TEXT="oder mu&#xdf; in die dort erzeugte Datenstruktur nachtr&#xe4;glich gespeichert werden"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687039717162" ID="ID_59086385" MODIFIED="1687039770869" TEXT="L&#xf6;sungsansatz: Expander arbeitet bereits auf JobPlanning als Datenstruktur">
<icon BUILTIN="idea"/>
<node CREATED="1687039778410" ID="ID_696364803" MODIFIED="1687039807242" TEXT="damit w&#xe4;re das (etwas sonderbare) Tupel aus JobPlanning-Pointern abzul&#xf6;sen"/>
<node CREATED="1687040058436" ID="ID_1402323400" MODIFIED="1687040071534" TEXT="JobPlanning h&#xe4;tte dann einen &#xbb;chaining-ctor&#xab;"/>
<node COLOR="#435e98" CREATED="1687042205845" ID="ID_1147372599" MODIFIED="1687043621026" TEXT="Performance-Konsequenzen">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1687042313601" ID="ID_891484053" MODIFIED="1687042479747" TEXT="redundante Storage f&#xfc;r die JobTIcket* f&#xe4;llt weg">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
da im JobPlanning nochmal eine JobTicket&amp; liegt, sind die zwei bisher im darunter liegenden Tupel gespeicherten JobTicket* eigentlich redundant und werden nur f&#252;r die Explorer-Mechanik gebraucht
</p>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1687042241003" ID="ID_513934853" MODIFIED="1687042834774" TEXT="erheblicher Speicher-Mehrverbrauch im Explorer">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
weil nun auf jeder Ebene im Explorer-Stack eine JobPlanning-Instanz liegt, und zwar dort im ItemWrapper f&#252;r den jeweiligen TransformIterator (der die Explorer-Funktion implementiert)
</p>
</body>
</html></richcontent>
<icon BUILTIN="clanbomber"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1687042899983" ID="ID_55365542" MODIFIED="1687042927481" TEXT="Moves werden aufwendiger (Kopieren von Wert-Tupeln)">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687042939750" ID="ID_573111234" MODIFIED="1687043351665" TEXT="l&#xe4;&#xdf;t sich abmildern &#x27f9; FrameCoord per Referenz nehmen">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1687043326502" ID="ID_1349100996" MODIFIED="1687043610100" TEXT="nach Aussch&#xf6;pfen der Optimierung gar nicht mehr so schlimm">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Wenn man die Daten entsprechend reorganisiert und dadurch die Redundanzen in der Pipeline minimiert kann der Optimiser viel machen, da (private) Referenzen &#252;berhaupt nicht repr&#228;sentiert werden m&#252;ssen, sofern die referenzierte Quelle (wie hier) stabil im gleichen Objekt liegt. Wenn ich richtig sch&#228;tze, habe ich mit dem Umbau nur einen &#187;slot&#171; mehr Speicher verbraucht (weil drei redundante &#187;slots&#171; wegfallen k&#246;nnen)
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1687043611150" ID="ID_106958242" MODIFIED="1687043617395" TEXT="go for it!">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687043634555" ID="ID_71179253" MODIFIED="1687044340413" TEXT="Umschichten der Daten">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687044201408" ID="ID_1507798641" MODIFIED="1687047110612" TEXT="die Deadline sollte man als Wert speichern (caching)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...denn sonst w&#252;rde es genau zu rekursiven kaskadierenden (exponentiell aufwendigen) Aufrufen der Deadline-Berechnungs-Logik kommen; um das Caching zu steuern, kann ich einen Marker-Wert Time::NEVER verwenden
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687043695271" ID="ID_497206730" MODIFIED="1687044319733" TEXT="JobTicket-parent-Pointer in JobPlanning-parent verwandeln">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<b><font color="#f32157">AUA</font></b>: dieser parent-Pointer war bisher sogar eine <i>dangling reference </i>&#8212; er zeigte n&#228;mlich auf einen Pointer im Stack-Frame des &#955;-Aufrufs, der aber gar nicht mehr existiert, wenn man den Transform-Iterator auswertet. Soschnellkannsgehen
</p>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687043645122" ID="ID_1471106329" MODIFIED="1687047113108" TEXT="FrameCoord m&#xfc;ssen bereits in den TickGenerator">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...denn sonst m&#252;&#223;te ich sie in eine &#955;-Closure binden, was aber f&#252;r zwei der drei Felder redundate Storage w&#228;re; es macht auch sonst Sinn, wenn der Tick-Generator eben auf den FrameCoord arbeitet
</p>
</body>
</html></richcontent>
<node CREATED="1687047126863" ID="ID_1211205955" MODIFIED="1687047136938" TEXT="das ist aber nicht sch&#xf6;n">
<icon BUILTIN="smily_bad"/>
</node>
<node CREATED="1687047139677" ID="ID_1123653637" MODIFIED="1687047160987" TEXT="es bl&#xe4;ht den TickGenerator auf und macht ihn asymetrisch"/>
<node CREATED="1687047169092" ID="ID_1819824079" MODIFIED="1687047186765">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
dann m&#252;ssen die FrameCoord jetzt <b>sterben</b>
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
<node CREATED="1687047218784" ID="ID_965148273" MODIFIED="1687047467443" TEXT="sie werden eigentlich nie wirklich zusammen gebraucht">
<arrowlink COLOR="#9f154b" DESTINATION="ID_354859977" ENDARROW="Default" ENDINCLINATION="867;47;" ID="Arrow_ID_715252746" STARTARROW="None" STARTINCLINATION="-226;-425;"/>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1687047521489" ID="ID_1343365951" MODIFIED="1687047537890" TEXT="meistens sind sie nur halb g&#xfc;ltig &#x2014; oder redundant"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687047541216" ID="ID_3859431" MODIFIED="1687047560873" TEXT="wichtige bestehende Verwendungen">
<icon BUILTIN="info"/>
<node COLOR="#338800" CREATED="1687047579697" ID="ID_737360799" MODIFIED="1687052483835" TEXT="JobTicket::createJobFor (FrameCoord)">
<icon BUILTIN="button_ok"/>
<node CREATED="1687047618686" ID="ID_1365656833" MODIFIED="1687047628283">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
verwendet nur absoluteNominalTime
</p>
</body>
</html></richcontent>
<icon BUILTIN="info"/>
</node>
<node COLOR="#338800" CREATED="1687047629475" ID="ID_1969143286" MODIFIED="1687052485668" TEXT="direkt nehmen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#435e98" CREATED="1687047634050" ID="ID_663032785" MODIFIED="1687052486714" TEXT="damit fallen sie aus vielen Tests weg">
<icon BUILTIN="idea"/>
</node>
</node>
<node COLOR="#5b280f" CREATED="1687047718249" ID="ID_522193319" MODIFIED="1687052473908" TEXT="DispatchTable::locateRelative (FrameCoord, FrameCnt)">
<icon BUILTIN="button_cancel"/>
<node CREATED="1687047726324" ID="ID_618604807" MODIFIED="1687047732761" TEXT="ist eh schon stillgelegt"/>
</node>
<node COLOR="#5b280f" CREATED="1687047796700" ID="ID_1266801851" MODIFIED="1687052429106" TEXT="FrameSequencer::getNextFrame (FrameCoord)">
<icon BUILTIN="button_cancel"/>
<node CREATED="1687047808307" ID="ID_539998564" MODIFIED="1687047816009" TEXT="dto... nicht mehr verwendet"/>
<node COLOR="#338800" CREATED="1687047841006" ID="ID_480900539" MODIFIED="1687052420738" TEXT="FrameSequencer insgesamt &#xfc;berfl&#xfc;ssig">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1687047986424" ID="ID_1866280940" MODIFIED="1687052469428" TEXT="FrameLocator::getJobTicketFor (FrameCoord)">
<icon BUILTIN="button_ok"/>
<node CREATED="1687047995665" ID="ID_1960158539" MODIFIED="1687048015259">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
das ist die <i>einzige Verwendung</i>&#160;von zwei Feldern
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1687048209934" ID="ID_258966675" MODIFIED="1687048220362" TEXT="Verwendungen">
<icon BUILTIN="info"/>
<node CREATED="1687048232475" ID="ID_564390430" MODIFIED="1687048406468" TEXT="PipelineBuilder::pullFrom()">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Das ist <i>genau der Grund warum sie jetzt zum Problem</i>&#160;werden: diese Funktion erzeugt FrameCoord, die irgendwo leben m&#252;ssen, und das blo&#223;, um den einen Aufruf zu machen. Das <b>best&#228;tigt die Enscheidung</b>, sie zur&#252;ckzubauen
</p>
</body>
</html></richcontent>
<linktarget COLOR="#fafede" DESTINATION="ID_564390430" ENDARROW="Default" ENDINCLINATION="-200;20;" ID="Arrow_ID_141914814" SOURCE="ID_1690783604" STARTARROW="None" STARTINCLINATION="127;-8;"/>
</node>
<node CREATED="1687048434734" ID="ID_1902873210" MODIFIED="1687048446376" TEXT="JobPlanning_test : getJobTicket..."/>
<node CREATED="1687048458307" ID="ID_1324647389" MODIFIED="1687048595459" TEXT="dispatcher.getJobTicketFor(frame).createJobFor(frame)">
<arrowlink DESTINATION="ID_650695722" ENDARROW="Default" ENDINCLINATION="114;-7;" ID="Arrow_ID_1664199496" STARTARROW="None" STARTINCLINATION="114;6;"/>
</node>
</node>
<node CREATED="1687048477373" ID="ID_810957582" MODIFIED="1687048487150" TEXT="alle Verwendungen nur auf dem Dispatcher">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#338800" CREATED="1687048516587" ID="ID_1263916587" MODIFIED="1687052444704" TEXT="FrameLocator insgesamt &#xfc;berfl&#xfc;ssig">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1687048542480" ID="ID_313742999" MODIFIED="1687052450991" TEXT="Dispatcher-Umbau">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1687048547919" ID="ID_1929140105" MODIFIED="1687052453813" TEXT="getJobTicket wird virtuelle Funktion (nun public)">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1687048568620" ID="ID_650695722" MODIFIED="1687052452753" TEXT="convenience-shortcut f&#xfc;r den Test-Bandwurm">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_650695722" ENDARROW="Default" ENDINCLINATION="114;-7;" ID="Arrow_ID_1664199496" SOURCE="ID_1324647389" STARTARROW="None" STARTINCLINATION="114;6;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687047874264" ID="ID_59699296" MODIFIED="1687047879655" TEXT="Feld in JobPlanning">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1687047881181" ID="ID_1499402798" MODIFIED="1687047886577" TEXT="grade neu gebaut">
<icon BUILTIN="ksmiletris"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687047888296" ID="ID_1054027313" MODIFIED="1687047916199" TEXT="m&#xf6;glichst durch Referenzen ersetzen">
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1687048371598" ID="ID_1690783604" MODIFIED="1687048406468" TEXT="best&#xe4;tigt: gute Enscheidung">
<arrowlink COLOR="#fafede" DESTINATION="ID_564390430" ENDARROW="Default" ENDINCLINATION="-200;20;" ID="Arrow_ID_141914814" STARTARROW="None" STARTINCLINATION="127;-8;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1687044355596" ID="ID_1593217439" MODIFIED="1687044369362" TEXT="JobPlanningPipeline_test anpassen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1687044370372" ID="ID_1608005431" MODIFIED="1687044408084" TEXT="der hat bisher das JobTIcket-Tupel verwendet">
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1687044384151" ID="ID_228309908" MODIFIED="1687044397980" TEXT="ggfs speziellen Accessor schaffen?">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="help"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686840122729" ID="ID_1592165499" MODIFIED="1686840132630" TEXT="Ergebnis">
@ -76568,7 +76885,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685057532500" ID="ID_1172676625" MODIFIED="1685057709903" TEXT="&#x27f9; brauche ein Matching auf passende Ports">
<arrowlink COLOR="#fb1160" DESTINATION="ID_106757636" ENDARROW="Default" ENDINCLINATION="-78;630;" ID="Arrow_ID_1247503914" STARTARROW="None" STARTINCLINATION="1444;-44;"/>
<arrowlink COLOR="#fb1160" DESTINATION="ID_106757636" ENDARROW="Default" ENDINCLINATION="-78;630;" ID="Arrow_ID_1247503914" STARTARROW="None" STARTINCLINATION="1533;-30;"/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>