Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data Product Copier #46

Merged
merged 11 commits into from
Jun 18, 2024
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
--------------------------------------------------------------------------------
-- Product_Copier Component Implementation Body
--------------------------------------------------------------------------------

with Data_Product_Types; use Data_Product_Types;
with Data_Product_Enums;

package body Component.Product_Copier.Implementation is

--------------------------------------------------
-- Subprogram for implementation init method:
--------------------------------------------------
-- At initialization, this component requires a list of source/destination pairs
-- of data products to copy.
--
-- Init Parameters:
-- Products_To_Copy : Product_Mapping_Array_Access - The list of mappings to be
-- copied by this component every tick. Raises an error on Init if the list is
-- null, as well as if two mappings share a destination.
-- You must pass a reference (using 'Access) to this function, and as a
-- consequence you can't declare your array of mappings within, say, a function's
-- declarative region, since it must not be garbage collected. Either declare it
-- in a package or use a dynamic allocation.
-- Send_Event_On_Source_Id_Out_Of_Range : Boolean - When the status of a fetch is
-- of Id_Out_Of_Range, specifies whether an error event should be sent. This could
-- indicate misconfiguration, so sending error events is the default.
-- Send_Event_On_Source_Not_Available : Boolean - When the status of a fetch is of
-- Not_Available, specifies whether an error event should be sent. This might
-- simply indicate that the product is not yet ready to be fetched, in which case
-- this is expected behavior. Accordingly, not sending error events is the
-- default.
--
overriding procedure Init (Self : in out Instance; Products_To_Copy : in Product_Mapping_Array_Access; Send_Event_On_Source_Id_Out_Of_Range : in Boolean := True; Send_Event_On_Source_Not_Available : in Boolean := False) is
begin
-- make sure no two destinations have the same ID, otherwise raise an error
for I in Products_To_Copy'Range loop
for J in I + 1 .. Products_To_Copy'Last loop
pragma Assert (
Products_To_Copy (I).Destination_Id /= Products_To_Copy (J).Destination_Id
);
end loop;
end loop;

-- copy configuration to component record
Self.Send_Event_On_Source_Id_Out_Of_Range := Send_Event_On_Source_Id_Out_Of_Range;
Self.Send_Event_On_Source_Not_Available := Send_Event_On_Source_Not_Available;
pragma Assert (Products_To_Copy /= null);
Self.Mappings := Products_To_Copy;
dinkelk marked this conversation as resolved.
Show resolved Hide resolved
end Init;

---------------------------------------
-- Invokee connector primitives:
---------------------------------------
-- Triggers copying of data products (through request and send connectors).
overriding procedure Tick_T_Recv_Sync (Self : in out Instance; Arg : in Tick.T) is
begin
for Mapping of Self.Mappings.all loop
declare
use Data_Product_Enums;
use Data_Product_Enums.Fetch_Status; -- required for `=` operator
-- fetch source
Dp_Return : constant Data_Product_Return.T :=
Self.Data_Product_Fetch_T_Request ((Id => Mapping.Source_Id));
begin
case Dp_Return.The_Status is
-- send error events if applicable
when Fetch_Status.Not_Available =>
if Self.Send_Event_On_Source_Not_Available then
Self.Event_T_Send_If_Connected (
Self.Events.Source_Not_Available (
Self.Sys_Time_T_Get,
(
Tick => Arg.Count,
Mapping => Mapping
)
)
);
end if;
when Fetch_Status.Id_Out_Of_Range =>
if Self.Send_Event_On_Source_Id_Out_Of_Range then
Self.Event_T_Send_If_Connected (
Self.Events.Source_Id_Out_Of_Range (
Self.Sys_Time_T_Get,
(
Tick => Arg.Count,
Mapping => Mapping
)
)
);
end if;

-- send to dest
when Fetch_Status.Success =>
Self.Data_Product_T_Send (Dp_Return.The_Data_Product);
end case;
end;
end loop;
end Tick_T_Recv_Sync;

end Component.Product_Copier.Implementation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
--------------------------------------------------------------------------------
-- Product_Copier Component Implementation Spec
--------------------------------------------------------------------------------

-- Includes:
with Tick;

-- Given two locations and a list of source/destination IDs, fetches Data_Product
-- entries from one location and sends/copies them to another upon receiving a
-- Tick.
-- The use case in mind was for the two locations to be databases (e.g.
-- Product_Database instances), and for this component to take snapshots of a
-- source database at a fixed interval. The idea is that if the values stored in
-- source database is constantly in flux, then the destination database could
-- provide a stable view of the source -- within a tick, the values in the
-- destination database will not change between reads.
package Component.Product_Copier.Implementation is

-- The component class instance record:
type Instance is new Product_Copier.Base_Instance with private;

--------------------------------------------------
-- Subprogram for implementation init method:
--------------------------------------------------
-- At initialization, this component requires a list of source/destination pairs
-- of data products to copy.
--
-- Init Parameters:
-- Products_To_Copy : Product_Mapping_Array_Access - The list of mappings to be
-- copied by this component every tick. Raises an error on Init if the list is
-- null, as well as if two mappings share a destination.
-- You must pass a reference (using 'Access) to this function, and as a
-- consequence you can't declare your array of mappings within, say, a function's
-- declarative region, since it must not be garbage collected. Either declare it
-- in a package or use a dynamic allocation.
-- Send_Event_On_Source_Id_Out_Of_Range : Boolean - When the status of a fetch is
-- of Id_Out_Of_Range, specifies whether an error event should be sent. This could
-- indicate misconfiguration, so sending error events is the default.
-- Send_Event_On_Source_Not_Available : Boolean - When the status of a fetch is of
-- Not_Available, specifies whether an error event should be sent. This might
-- simply indicate that the product is not yet ready to be fetched, in which case
-- this is expected behavior. Accordingly, not sending error events is the
-- default.
--
overriding procedure Init (Self : in out Instance; Products_To_Copy : in Product_Mapping_Array_Access; Send_Event_On_Source_Id_Out_Of_Range : in Boolean := True; Send_Event_On_Source_Not_Available : in Boolean := False);

private

-- The component class instance record:
type Instance is new Product_Copier.Base_Instance with record
Send_Event_On_Source_Id_Out_Of_Range : Boolean := True;
Send_Event_On_Source_Not_Available : Boolean := False;
Mappings : Product_Mapping_Array_Access := null;
end record;

---------------------------------------
-- Set Up Procedure
---------------------------------------
-- Null method which can be implemented to provide some component
-- set up code. This method is generally called by the assembly
-- main.adb after all component initialization and tasks have been started.
-- Some activities need to only be run once at startup, but cannot be run
-- safely until everything is up and running, ie. command registration, initial
-- data product updates. This procedure should be implemented to do these things
-- if necessary.
overriding procedure Set_Up (Self : in out Instance) is null;

---------------------------------------
-- Invokee connector primitives:
---------------------------------------
-- Triggers copying of data products (through request and send connectors).
overriding procedure Tick_T_Recv_Sync (Self : in out Instance; Arg : in Tick.T);

---------------------------------------
-- Invoker connector primitives:
---------------------------------------
-- This procedure is called when a Data_Product_T_Send message is dropped due to a full queue.
overriding procedure Data_Product_T_Send_Dropped (Self : in out Instance; Arg : in Data_Product.T) is null;
-- This procedure is called when a Event_T_Send message is dropped due to a full queue.
overriding procedure Event_T_Send_Dropped (Self : in out Instance; Arg : in Event.T) is null;

end Component.Product_Copier.Implementation;
Binary file not shown.
83 changes: 83 additions & 0 deletions src/components/product_copier/doc/product_copier.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
\input{common_packages.tex}

\begin{document}

\title{\textbf{Product Copier} \\
\large\textit{Component Design Document}}
\date{}
\maketitle

\section{Description}
\input{build/tex/product_copier_description.tex}

\section{Requirements}
\input{build/tex/product_copier_requirements.tex}

\section{Design}

\subsection{At a Glance}
\input{build/tex/product_copier_stats.tex}

\subsection{Diagram}
\begin{figure}[H]
\includegraphics[width=1.0\textwidth,center]{../build/eps/product_copier.eps}
\caption{Product Copier component diagram.}
\end{figure}

\subsection{Connectors}
\input{build/tex/product_copier_connectors.tex}

\subsection{Interrupts}

\input{build/tex/product_copier_interrupts.tex}

\subsection{Initialization}
\input{build/tex/product_copier_init.tex}

\subsection{Commands}

\input{build/tex/product_copier_commands.tex}

\subsection{Parameters}

\input{build/tex/product_copier_parameters.tex}

\subsection{Events}

\input{build/tex/product_copier_events.tex}

\subsection{Data Products}

\input{build/tex/product_copier_data_products.tex}

\subsection{Data Dependencies}

\input{build/tex/product_copier_data_dependencies.tex}

\subsection{Packets}

\input{build/tex/product_copier_packets.tex}

\subsection{Faults}

\input{build/tex/product_copier_faults.tex}

\section{Unit Tests}

\input{build/tex/product_copier_unit_test.tex}

\section{Appendix}

\subsection{Preamble}

\input{build/tex/product_copier_preamble.tex}

\subsection{Packed Types}

\input{build/tex/product_copier_types.tex}

\subsection{Enumerations}

\input{build/tex/product_copier_enums.tex}

\end{document}
45 changes: 45 additions & 0 deletions src/components/product_copier/product_copier.component.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
description: |
Given two locations and a list of source/destination IDs, fetches Data_Product entries from one location and sends/copies them to another upon receiving a Tick.

A typical use case is for the two locations to be databases (e.g. Product_Database instances), and for this component to take snapshots of products in a source database at a fixed interval. While values stored in the source database may constantly be in flux, the destination database could provide a stable view of the source -- within a tick, the values in the destination database will not change between reads.
execution: passive
with:
- Product_Mapping
preamble: |
type Product_Mapping_Array is array (Natural range <>) of Product_Mapping.T;
type Product_Mapping_Array_Access is access all Product_Mapping_Array;
init:
description: |
At initialization, this component requires a list of source/destination pairs of data products to copy.
parameters:
- name: Products_To_Copy
type: Product_Mapping_Array_Access
description: The list of mappings to be copied by this component every tick. Raises an error on Init if the list is null, as well as if two mappings share a destination.
- name: Send_Event_On_Source_Id_Out_Of_Range
type: Boolean
default: "True"
description: When the status of a fetch is of Id_Out_Of_Range, specifies whether an error event should be sent. This could indicate misconfiguration, so sending error events is the default.
- name: Send_Event_On_Source_Not_Available
type: Boolean
default: "False"
description: When the status of a fetch is of Not_Available, specifies whether an error event should be sent. This might simply indicate that the product is not yet ready to be fetched, in which case this is expected behavior. Accordingly, not sending error events is the default.
connectors:
# invokee
- type: Tick.T
kind: recv_sync
description: Triggers copying of data products (through request and send connectors).
# invokers
- type: Data_Product.T
kind: send
description: The destination for fetched data products to be sent to.
- type: Data_Product_Fetch.T
return_type: Data_Product_Return.T
kind: request
description: Where data products are copied from.
- type: Event.T
kind: send
description: Any produced events are sent out this connector.
- return_type: Sys_Time.T
kind: get
description: Time stamps for events are fetched via this connector.
8 changes: 8 additions & 0 deletions src/components/product_copier/product_copier.events.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
events:
- name: Source_Not_Available
description: A data product fetch resulted in an a Not_Available status, and was not sent to the destination.
param_type: Product_Copier_Error_Info.T
dinkelk marked this conversation as resolved.
Show resolved Hide resolved
- name: Source_Id_Out_Of_Range
description: A data product fetch resulted in an an Id_Out_Of_Range status, and was not sent to the destination.
param_type: Product_Copier_Error_Info.T
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
description: The requirements of the component.
requirements:
- text: The component shall copy data products from one location to another, every time it is sent a Tick, given a list of source ID/destination ID mappings.
- text: The component shall fail at initialization when two mappings share the same destination ID.
description: When two mappings share the same destination, it's unclear which one should "win" and write to the destination first. If the user requires some kind of overwriting behavior, they can make this explicit by instantiating another of this component. (Assuming the send connector is connected to some kind of database write operation.)
- text: If fetching from the source results in the data product not being available or the requested ID is out of range, no data product will be copied, and execution will continue. It will raise an error event if configured to do so.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
description: To be sent in error events, specifying which source, destination, and tick caused the error.
fields:
- name: Tick
description: The count of the tick that caused the error.
type: Interfaces.Unsigned_32 # these fields copy the format of tick.record.yaml
format: U32
- name: Mapping
type: Product_Mapping.T
10 changes: 10 additions & 0 deletions src/components/product_copier/product_mapping.record.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
description: A source/destination ID pair that specifies where data products should be copied to/from
fields:
# chose U16 to match Id in Data_Product_Header
- name: Source_Id
type: Data_Product_Types.Data_Product_Id
format: U16
- name: Destination_Id
type: Data_Product_Types.Data_Product_Id
format: U16
Loading