Keyword mapping refactoring
This commit is contained in:
+47
-47
@@ -20,26 +20,17 @@ uses
|
||||
type
|
||||
TImportConverter = reference to procedure(const Src: Pointer; Dst: TScalar.PValue);
|
||||
|
||||
// Interface representing a read-only view of a specific data row.
|
||||
IScalarRecord = interface
|
||||
function GetDef: IScalarRecordDefinition;
|
||||
function GetItems(const Key: IKeyword): TScalar;
|
||||
|
||||
function ItemByIndex(Idx: Integer): TScalar;
|
||||
|
||||
property Def: IScalarRecordDefinition read GetDef;
|
||||
property Items[const Key: IKeyword]: TScalar read GetItems; default;
|
||||
end;
|
||||
|
||||
IScalarRecordFeed = interface
|
||||
procedure ClearCache;
|
||||
{$region 'private'}
|
||||
function GetTicker: TProducer<IScalarRecord>;
|
||||
{$endregion}
|
||||
|
||||
procedure SetImportOptions(RecordSize: Integer; const Converter: TImportConverter);
|
||||
function EnumerateSymbols: TFuture<TArray<String>>;
|
||||
|
||||
// Streaming processing: Reads data from disk and broadcasts it via Ticker
|
||||
function ProcessData(const Symbol: String; const Terminated: TState): TState;
|
||||
|
||||
function GetTicker: TProducer<IScalarRecord>;
|
||||
property Ticker: TProducer<IScalarRecord> read GetTicker;
|
||||
end;
|
||||
|
||||
@@ -79,7 +70,7 @@ type
|
||||
FFileExtension: String;
|
||||
FIsCompressed: Boolean;
|
||||
|
||||
FCachedFiles: TDataFileCache<TArray<TBatch>>;
|
||||
FCachedFiles: IDataFileCache<TArray<TBatch>>;
|
||||
FSymbols: TFuture<TDictionary<String, TArray<TDataFile>>>;
|
||||
|
||||
// Producer implementation
|
||||
@@ -116,10 +107,14 @@ type
|
||||
function GetTicker: TProducer<IScalarRecord>;
|
||||
|
||||
public
|
||||
constructor Create(const APath: String; const AExtension: String; IsCompressed: Boolean; const ADef: IScalarRecordDefinition);
|
||||
constructor Create(
|
||||
const ACachedFiles: IDataFileCache<TArray<TBatch>>;
|
||||
const APath, AExtension: String;
|
||||
IsCompressed: Boolean;
|
||||
const ADef: IScalarRecordDefinition
|
||||
);
|
||||
destructor Destroy; override;
|
||||
procedure AfterConstruction; override;
|
||||
procedure ClearCache;
|
||||
|
||||
procedure SetImportOptions(RecordSize: Integer; const Converter: TImportConverter);
|
||||
function EnumerateSymbols: TFuture<TArray<String>>;
|
||||
@@ -152,14 +147,15 @@ type
|
||||
private
|
||||
FDef: IScalarRecordDefinition;
|
||||
FData: TScalar.PValue;
|
||||
|
||||
// IKeywordMapping<TScalar.TValue> implementation
|
||||
function IndexOf(const Key: IKeyword): Integer;
|
||||
function GetCount: Integer;
|
||||
function GetItems(Idx: Integer): TPair<IKeyword, TScalar>;
|
||||
function GetFields(const Key: IKeyword): TScalar;
|
||||
public
|
||||
constructor Create(const ADef: IScalarRecordDefinition);
|
||||
procedure SetData(const AData: TScalar.PValue); inline;
|
||||
|
||||
function ItemByIndex(Idx: Integer): TScalar; inline;
|
||||
|
||||
function GetDef: IScalarRecordDefinition;
|
||||
function GetItems(const Key: IKeyword): TScalar;
|
||||
end;
|
||||
|
||||
{ TScalarRecordView }
|
||||
@@ -175,26 +171,34 @@ begin
|
||||
FData := AData;
|
||||
end;
|
||||
|
||||
function TScalarRecordView.GetDef: IScalarRecordDefinition;
|
||||
function TScalarRecordView.GetCount: Integer;
|
||||
begin
|
||||
Result := FDef;
|
||||
Result := FDef.Count;
|
||||
end;
|
||||
|
||||
function TScalarRecordView.GetItems(const Key: IKeyword): TScalar;
|
||||
function TScalarRecordView.GetFields(const Key: IKeyword): TScalar;
|
||||
var
|
||||
idx: Integer;
|
||||
begin
|
||||
// Optimization: Depending on hot-path usage, one could cache the Fields array
|
||||
// or use direct index access if the definition allows.
|
||||
var idx := FDef.IndexOf(Key);
|
||||
idx := FDef.IndexOf(Key);
|
||||
if idx < 0 then
|
||||
exit(TScalar.Create(TScalar.TKind.Ordinal, Default(TScalar.TValue)));
|
||||
exit(Default(TScalar));
|
||||
|
||||
Result := ItemByIndex(idx);
|
||||
// Return the raw TValue at the offset
|
||||
Result.Kind := FDef[idx].Value;
|
||||
Result.Value := TScalar.PValue(NativeUInt(FData) + NativeUInt(idx * SizeOf(TScalar.TValue)))^;
|
||||
end;
|
||||
|
||||
function TScalarRecordView.ItemByIndex(Idx: Integer): TScalar;
|
||||
function TScalarRecordView.GetItems(Idx: Integer): TPair<IKeyword, TScalar>;
|
||||
begin
|
||||
// Calculate pointer offset
|
||||
Result.Create(FDef.Fields[Idx].Value, TScalar.PValue(NativeUInt(FData) + NativeUInt(idx * SizeOf(TScalar.TValue)))^);
|
||||
Result.Key := FDef[Idx].Key;
|
||||
Result.Value.Kind := FDef[idx].Value;
|
||||
Result.Value.Value := TScalar.PValue(NativeUInt(FData) + NativeUInt(Idx * SizeOf(TScalar.TValue)))^;
|
||||
end;
|
||||
|
||||
function TScalarRecordView.IndexOf(const Key: IKeyword): Integer;
|
||||
begin
|
||||
Result := FDef.IndexOf(Key);
|
||||
end;
|
||||
|
||||
{ TScalarRecordFeed.TDataFile }
|
||||
@@ -227,8 +231,8 @@ end;
|
||||
{ TScalarRecordFeed }
|
||||
|
||||
constructor TScalarRecordFeed.Create(
|
||||
const APath: String;
|
||||
const AExtension: String;
|
||||
const ACachedFiles: IDataFileCache<TArray<TBatch>>;
|
||||
const APath, AExtension: String;
|
||||
IsCompressed: Boolean;
|
||||
const ADef: IScalarRecordDefinition
|
||||
);
|
||||
@@ -236,6 +240,7 @@ begin
|
||||
inherited Create;
|
||||
FPath := APath;
|
||||
FDef := ADef;
|
||||
FCachedFiles := ACachedFiles;
|
||||
FFileExtension := AExtension;
|
||||
FIsCompressed := IsCompressed;
|
||||
FLookback := -1;
|
||||
@@ -244,15 +249,12 @@ begin
|
||||
|
||||
FTicker := TMycContainedProducer<IScalarRecord>.Create(Self);
|
||||
|
||||
FCachedFiles :=
|
||||
TDataFileCache<TArray<TBatch>>
|
||||
.Create(function(const Filename: String): TFuture<TArray<TBatch>> begin Result := DoLoad(Filename, FLoadGate); end);
|
||||
FCachedFiles := TDataFileCache<TArray<TBatch>>.Create;
|
||||
end;
|
||||
|
||||
destructor TScalarRecordFeed.Destroy;
|
||||
begin
|
||||
ClearCache;
|
||||
FCachedFiles.Free;
|
||||
FCachedFiles.Clear;
|
||||
FTicker.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
@@ -263,16 +265,10 @@ begin
|
||||
UpdateSymbols;
|
||||
end;
|
||||
|
||||
procedure TScalarRecordFeed.ClearCache;
|
||||
begin
|
||||
FCachedFiles.Clear;
|
||||
end;
|
||||
|
||||
procedure TScalarRecordFeed.SetImportOptions(RecordSize: Integer; const Converter: TImportConverter);
|
||||
begin
|
||||
FImportRecordSize := RecordSize;
|
||||
FImportConverter := Converter;
|
||||
ClearCache;
|
||||
end;
|
||||
|
||||
function TScalarRecordFeed.GetPath: String;
|
||||
@@ -443,7 +439,11 @@ end;
|
||||
function TScalarRecordFeed.LoadDataFile(const DataFile: TDataFile): TFuture<TArray<TBatch>>;
|
||||
begin
|
||||
if DataFile.IsValid then
|
||||
Result := FCachedFiles.GetOrAdd(DataFile.GetFullFileName)
|
||||
Result :=
|
||||
FCachedFiles.GetOrAdd(
|
||||
DataFile.GetFullFileName,
|
||||
function(const Filename: String): TFuture<TArray<TBatch>> begin Result := DoLoad(Filename, FLoadGate); end
|
||||
)
|
||||
else
|
||||
Result := TFuture<TArray<TBatch>>.Construct(TArray<TBatch>(nil));
|
||||
end;
|
||||
@@ -551,7 +551,7 @@ begin
|
||||
InputStream.Position := 0;
|
||||
fileSize := InputStream.Size;
|
||||
|
||||
fieldsPerRecord := Length(FDef.Fields);
|
||||
fieldsPerRecord := FDef.Count;
|
||||
internalRecordSize := fieldsPerRecord * sizeof(TScalar.TValue);
|
||||
|
||||
if (FImportRecordSize > 0) and Assigned(FImportConverter) then
|
||||
|
||||
Reference in New Issue
Block a user