Class NcResultRecorder
- Namespace
- Hi.MachiningProcs
- Assembly
- HiNc.dll
Internal Use Only. The recorder of one play's result file (the NC play result recording's
P3): the IMachiningResultSink the play's three threads hand their records to, a
queue, and one writer thread of its own that feeds a SqliteNcResultWriter
(Create(string, string)). The recorder is begun armed, with no file: the
file and its folder (Output/results/[NcName]-[timestamp]/result.db by default, the
template relative to the project folder, the name the first recorded piece's program) are
created on the writer thread when the first record reaches it, so a section that records
nothing leaves nothing behind. The play's threads never wait on it: a record is offered to a
bounded queue, and a record the full queue refuses – the disk stalled,
or a play faster than the writer – is dropped and counted, the recording going on (the file's
order contract allows a gap; the recorder is Degraded from the
first drop and completes its file as a play that did not run to its end); a failure of the
storage turns it Failed, which leaves the file an orphan.
Nothing a record does reaches the play: every exception is caught here, counted and said once on
the progress.
The piece ids (the PieceId of the file) are issued here, by the piece's sentence snapshot
(Of(ISentenceCarrier), the same object the steps built from the piece carry) in
execution order from 0, at the piece's event; a step whose sentence had no piece event (a
legacy HardNc play, whose events carry no piece) gets no id. A piece's bytes are taken once
the pipeline has frozen the piece: the pieces wait in a queue of the recorder's own, the frozen
ones at its head are recorded at each piece event, and a piece that has waited past twice the
pipeline's freeze lag, or is still live when the recording ends (a stop, a reset, freezing
turned off), is serialized by the recorder itself.
The host (LocalProjectService) wires it: NotePosAdded(ClStripPos) to PosAdded, NoteSyntaxPieceRan(SyntaxPiece) to SyntaxPieceRan, the recorder itself to ResultSink, NotePlayEnded(bool) to the play's end, and calls Complete(bool, Action<string>) or Abort() when the section ends.
public sealed class NcResultRecorder : IMachiningResultSink, IDisposable
- Inheritance
-
NcResultRecorder
- Implements
- Inherited Members
- Extension Methods
Constructors
NcResultRecorder(string, string, string, IProgress<IMessage>, int)
Begins a recorder: armed, no file yet. The file is created when the first record reaches the
writer thread, in the folder relDirectoryTemplate names.
public NcResultRecorder(string baseDirectory, string relDirectoryTemplate, string fallbackNcName, IProgress<IMessage> progress, int queueCapacity = 131072)
Parameters
baseDirectorystringThe project folder a relative template is taken from; null for the current directory.
relDirectoryTemplatestringThe result folder's path: relative to
baseDirectory(an absolute path is used as it is), with NcNameToken and TimestampToken replaced; null for DefaultRelDirectoryTemplate. A folder that exists already gets-2,-3, ... appended.fallbackNcNamestringThe name for NcNameToken when no piece names a program before the file is created (a legacy HardNc play, a play of acts); null for
play.progressIProgress<IMessage>Where the recorder says what it did and what it could not; null for silence.
queueCapacityintThe records the queue holds at most (DefaultQueueCapacity); at least 1.
Exceptions
- ArgumentOutOfRangeException
queueCapacityis below 1.
Fields
DatabaseFileName
The result file's name in its folder.
public const string DatabaseFileName = "result.db"
Field Value
DefaultAbortDrainTimeout
The default of AbortDrainTimeout: 5 s.
public static readonly TimeSpan DefaultAbortDrainTimeout
Field Value
DefaultCompleteDrainTimeout
The default of CompleteDrainTimeout: 60 s.
public static readonly TimeSpan DefaultCompleteDrainTimeout
Field Value
DefaultQueueCapacity
The records the queue to the writer thread holds at most: about eight seconds of a play at the size spike's rate (three records a step, a step every 170-190 us) before records are dropped.
public const int DefaultQueueCapacity = 131072
Field Value
DefaultRelDirectoryTemplate
The default template of the result folder, relative to the project folder.
public const string DefaultRelDirectoryTemplate = "Output/results/[NcName]-[timestamp]"
Field Value
NcNameToken
The template token the recorded program's file name replaces (the first recorded piece's program, the project's name without one).
public const string NcNameToken = "[NcName]"
Field Value
TimestampToken
The template token the file's creation time replaces, yyyyMMdd-HHmmss local.
public const string TimestampToken = "[timestamp]"
Field Value
WctFileName
The finished stock's file name in the result folder.
public const string WctFileName = "finish.wct"
Field Value
Properties
AbortDrainTimeout
How long Abort() waits for the writer thread before it leaves it behind; DefaultAbortDrainTimeout unless set at the construction.
public TimeSpan AbortDrainTimeout { get; init; }
Property Value
CompleteDrainTimeout
How long Complete(bool, Action<string>) waits for the writer thread to drain the queue before it gives the file up as failed; DefaultCompleteDrainTimeout unless set at the construction.
public TimeSpan CompleteDrainTimeout { get; init; }
Property Value
Counts
The counts so far.
public NcResultRecorderCounts Counts { get; }
Property Value
DatabasePath
The full path of the result.db; null until the file is created.
public string DatabasePath { get; }
Property Value
Failure
The failure that turned the recorder Failed; null otherwise.
public Exception Failure { get; }
Property Value
FirstStepIndex
The lowest step index the file took (kept by the writer thread, so it lags the play by the queue); -1 without a step.
public int FirstStepIndex { get; }
Property Value
IsEmpty
Whether nothing was handed to the recorder that it would record: no record taken into its queue and no piece waiting for its freeze. A recorder that is empty when its section ends leaves no folder behind.
public bool IsEmpty { get; }
Property Value
LastStepIndex
The highest step index the file took (kept by the writer thread, so it lags the play by the queue); -1 without a step.
public int LastStepIndex { get; }
Property Value
PlayCutShort
Whether a recorded play was cut short – the licence's step cap, a lease that expired or a
step grant used up (NotePlayEnded(bool) with ranToEnd false) – which makes the
file's PlayCompleted false whatever else happened.
public bool PlayCutShort { get; }
Property Value
ResultDirectory
The result folder's full path; null until the file is created.
public string ResultDirectory { get; }
Property Value
State
Where the recorder stands.
public NcResultRecorderState State { get; }
Property Value
StepRecordedSincePlayEnd
Whether a step was recorded since the last NotePlayEnded(bool): false when every
recorded step belongs to a play that ran to its end, which is what makes the file's
PlayCompleted true at Complete(bool, Action<string>) unless the host says the run was stopped.
public bool StepRecordedSincePlayEnd { get; }
Property Value
Methods
Abort()
Abandons the recording: no record is taken from here on, the writer thread ends, the writer
is disposed without completing, and the file, if one was created, stays not completed, an
orphan (DeleteOrphanNcResults deletes it). Idempotent; a no-op after Complete(bool, Action<string>).
public void Abort()
AddClStripPos(in ClStripPosRecord)
A strip position, on PosAdded: the shell thread, outside the pipeline's submit lock; the position has no step yet.
public void AddClStripPos(in ClStripPosRecord pos)
Parameters
posClStripPosRecordThe position's record.
AddMachiningStep(MachiningStepRecord)
A published step, on the pump thread, after the step pipeline's fourth stage set the step on its position: the step's values of that moment.
public void AddMachiningStep(MachiningStepRecord step)
Parameters
stepMachiningStepRecordThe step's record.
AddStepBrief(StepBrief)
A published step's two briefs, on the pump thread, right after AddMachiningStep(MachiningStepRecord) for the same step: the force brief the force stage built (null when the physics did not run on the step) and the sequential physics state, never null for a published step. The briefs of the moment the step was published, taken once: what the step-physics recompute writes onto the step afterwards reaches a recording by the recorder's amend, never through this method.
public void AddStepBrief(StepBrief brief)
Parameters
briefStepBriefThe step's briefs, keyed by the step index.
AddSyntaxPiece(SyntaxPieceRecord)
A piece record taken already by the caller: its sentence gets an id when it has none yet, and the record goes to the file. The pipeline's pieces come through NoteSyntaxPieceRan(SyntaxPiece) instead, which waits for the freeze.
public void AddSyntaxPiece(SyntaxPieceRecord piece)
Parameters
pieceSyntaxPieceRecordThe piece's record.
Complete(bool, Action<string>)
Completes the recording: no record is taken from here on; the pieces still waiting are
recorded (the frozen ones as they are, the live ones serialized now); the queue is drained
and the writer thread ended; the finished stock is written by writeWct
to finish.wct in the result folder and hashed; then the file is completed
(Complete(bool, string, byte[])) with
playCompleted, forced false when the recorder degraded. A failure of
the stock's write is said and the file completed without a stock. A completion that throws
is told by the file's Meta: refused at its checkpoint or its switch out of WAL –
another connection looking at the file – it has its records and counts in, and its tail is
run again (TryFinalize(string)) up to three times, a fifth of a
second apart; a file still refused is said and left not completed
(NotFinalized: DeleteOrphanNcResults completes
it once no other program holds it). A completion that failed before its counts were written
leaves an orphan (Failed, said as such). Blocks the
caller for the stock's write and the completion; the host says so on the progress.
Idempotent: a second call answers the first's result.
public NcResultCompletion Complete(bool playCompleted, Action<string> writeWct)
Parameters
playCompletedboolWhether the recorded plays ran to their ends (the host decides, from the run's stop flag and StepRecordedSincePlayEnd); forced false when the recorder degraded or a play was cut short (PlayCutShort).
writeWctAction<string>Writes the finished stock to the full path it is given, or leaves no file there when there is no stock to write; null writes none (the service's dispose). A throw out of it is caught and said.
Returns
- NcResultCompletion
The outcome.
Complete(bool, Action<string>, Func<long[]>)
Complete(bool, Action<string>), with the finished stock's node map (the NC play result
recording's P5): once the stock is written and hashed, captureNodeAttachments is
called – on this thread, in the same still moment, the pipeline drained and the stock just written –
for the native attachment pointer of every strip position (index = step index, 0 for none), and the
keys go into the file (AddNodeAttachments(ReadOnlySpan<long>),
NcResult-Record–NodeMapWritten) before the completion. A review binds the stock's nodes to its
rebuilt positions by them, so the stock is coloured and picked by the steps as in the play. No stock
written (skipped or failed): the capture is not called. A throw out of the capture is said
(NcResult-Record–NodeMapFailed) and the file completes without a map: the stock shows plain
under review; the writer's own failure inside the write (SqliteException, a disposed
writer) is said as NcResult-Record–NodeMapWriteFailed, no completion is attempted on that
writer, and the outcome is a refused completion's (Failed or NotFinalized).
public NcResultCompletion Complete(bool playCompleted, Action<string> writeWct, Func<long[]> captureNodeAttachments)
Parameters
playCompletedboolwriteWctAction<string>captureNodeAttachmentsFunc<long[]>Answers the node keys by strip position index (0 for none), or null for no map; null writes no map.
Returns
- NcResultCompletion
The outcome.
Dispose()
Abort() when the recording was not completed. The queue is not disposed under a producer that may still offer to it; it goes with the recorder.
public void Dispose()
NotePlayEnded(bool)
A play ended (NcFileRan): the steps recorded so far belong to a finished play when it ran to its end; a play the licence cut short (the act runner's step refusal standing at the end) marks the file as not completed for good.
public void NotePlayEnded(bool ranToEnd = true)
Parameters
ranToEndboolWhether the play ran to its end rather than being cut short.
NotePosAdded(ClStripPos)
A strip position off PosAdded: its record is taken here (Of(ClStripPos)). A null position is ignored.
public void NotePosAdded(ClStripPos pos)
Parameters
posClStripPosThe position the strip added.
NoteSyntaxPieceRan(SyntaxPiece)
A piece the session ran (SyntaxPieceRan, the player's thread): its sentence's id is issued now, the program's name is taken off the first piece, and the piece waits in the recorder's queue until the pipeline freezes it – the frozen pieces at the queue's head are recorded now, and a piece that has waited past twice FreezeLagPieceCount boundaries is serialized live. A null piece (a legacy HardNc play) is counted and skipped.
public void NoteSyntaxPieceRan(SyntaxPiece piece)
Parameters
pieceSyntaxPieceThe piece; null for a legacy line.