JD2022-TU1/main/tools/extern/Bloomberg/Code/Libraries/Bloomberg.Message/Reader/DataInfoReader.cs

229 lines
No EOL
11 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using Bloomberg.Message.Entities;
using Bloomberg.Message.Utils;
namespace Bloomberg.Message.Reader
{
public class DataInfoReader
{
private readonly DataReader _dataReader = new DataReader();
private static log4net.ILog _log = log4net.LogManager.GetLogger(typeof(DataInfoReader));
public List<DataElement> Read(Stream currentStream, string savePath, ref bool errorDetected)
{
var dataList = new List<DataElement>();
uint lastReadMarker = ReadingForDataInfoStartMarker(dataList, currentStream, ref errorDetected);
if(lastReadMarker != MessageConstants.DataInfoStartMarker)
{
return dataList;
}
bool endOfDataList = false;
do
{
if(lastReadMarker != MessageConstants.DataStartMarker && lastReadMarker != MessageConstants.DataInfoEndMarker)
{
lastReadMarker = ReadUpToDataStartMarkerOrDataInfoEndMarker(dataList, currentStream, ref errorDetected);
}
switch (lastReadMarker)
{
case MessageConstants.DataStartMarker:
DataElement newDataElement = new DataElement();
try
{
_dataReader.Read(currentStream, savePath, ref newDataElement, ref errorDetected);
lastReadMarker = ReadUpToDataEndMarker(dataList, currentStream, ref errorDetected);
}
catch (Exception e)
{
errorDetected = true;
newDataElement.Error = $"DataInfoReader - Caught the following exception while reading: \r\n{e.Message}";
if (string.IsNullOrEmpty(newDataElement.Name))
{
newDataElement.Name = "n/a";
}
_log.Error("Error in DataInfoReader", e);
lastReadMarker = 0;
}
dataList.Add(newDataElement);
break;
case MessageConstants.DataInfoEndMarker:
//just continue
endOfDataList = true;
break;
default:
//no marker found. end parsing
_log.Warn("DataInfoReader - Bad marker found " + MessageConstants.GetMarkerName(lastReadMarker));
endOfDataList = true;
break;
}
}
while (!endOfDataList);
return dataList;
}
private uint ReadingForDataInfoStartMarker(List<DataElement> dataList, Stream currentStream, ref bool errorDetected)
{
while (true)
{
uint foundMarker;
if (ReaderHelper.ScanForSpecificMarkerNoSeek(currentStream, out foundMarker, MessageConstants.DataInfoStartMarker))
{
return foundMarker;
}
string foundMarkerName = MessageConstants.GetMarkerName(foundMarker);
switch (foundMarker)
{
case MessageConstants.DataInfoStartMarker:
//what we wanted, just keep going but log this and add error dataelement because it wasn't the first read that returned this constant
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
return foundMarker;
case MessageConstants.MessageEndMarker:
//just end streaming
return foundMarker;
case MessageConstants.ReportStartMarker:
case MessageConstants.ReportEndMarker:
case MessageConstants.DataInfoEndMarker:
case MessageConstants.VariableLengthStartMarker:
case MessageConstants.VariableLengthEndMarker:
case MessageConstants.DataEndMarker:
case MessageConstants.AttributeStartMarker:
case MessageConstants.AttributeEndMarker:
case MessageConstants.MessageStartMarker:
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected marker found before DataInfoStartMarker: {foundMarkerName}", dataList);
break;
case MessageConstants.DataStartMarker:
//next best thing, we can start a data element with this just rewind the stream a bit
MessageReader.LogErrorDataElement(ref errorDetected,
$"Unexpected marker found before DataInfoStartMarker: {foundMarkerName}. Continuing with parsing the message.", dataList);
return foundMarker;
default:
MessageReader.LogErrorDataElement(ref errorDetected, "No recognizeable marker found and end of stream reached while looking for DataInfoStartMarker", dataList);
return foundMarker;
}
}
}
private uint ReadUpToDataStartMarkerOrDataInfoEndMarker(List<DataElement> dataList, Stream currentStream, ref bool errorDetected)
{
while (true)
{
uint foundMarker;
if (ReaderHelper.ScanForSpecificMarkersNoSeek(currentStream, out foundMarker, MessageConstants.DataStartMarker, MessageConstants.DataInfoEndMarker))
{
return foundMarker;
}
string foundMarkerName = MessageConstants.GetMarkerName(foundMarker);
switch (foundMarker)
{
case MessageConstants.DataStartMarker:
//what we wanted, just keep going but log this and add error dataelement because it wasn't the first read that returned this constant
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
return foundMarker;
case MessageConstants.DataInfoEndMarker:
//the end of data info marker is found
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
return MessageConstants.DataInfoEndMarker;
case MessageConstants.MessageEndMarker:
//stop reading
MessageReader.LogErrorDataElement(ref errorDetected, $"Unrecognized data before marker {foundMarkerName}", dataList);
return MessageConstants.MessageEndMarker;
case MessageConstants.DataInfoStartMarker:
case MessageConstants.ReportStartMarker:
case MessageConstants.ReportEndMarker:
case MessageConstants.VariableLengthStartMarker:
case MessageConstants.VariableLengthEndMarker:
case MessageConstants.DataEndMarker:
case MessageConstants.AttributeStartMarker:
case MessageConstants.AttributeEndMarker:
case MessageConstants.MessageStartMarker:
MessageReader.LogErrorDataElement(ref errorDetected,
$"Unexpected marker found before DataInfoStartMarker or DataInfoEndMarker: {foundMarkerName}", dataList);
break;
default:
MessageReader.LogErrorDataElement(ref errorDetected, "No recognizeable marker found and end of stream reached while looking for DataInfoStartMarker or DataInfoEndMarker", dataList);
return 0;
}
}
}
private uint ReadUpToDataEndMarker(List<DataElement> dataList, Stream currentStream, ref bool errorDetected)
{
while (true)
{
uint foundMarker;
if (ReaderHelper.ScanForSpecificMarkerNoSeek(currentStream, out foundMarker, MessageConstants.DataEndMarker))
{
return foundMarker;
}
string foundMarkerName = MessageConstants.GetMarkerName(foundMarker);
switch (foundMarker)
{
case MessageConstants.DataStartMarker:
//the DataEndMarker is missing but keep reading to parse the new DataElement. Just rewind a little so the next scan for DataStartMarker works
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected marker found before marker DataEndMarker: {foundMarkerName}", dataList);
return foundMarker;
case MessageConstants.DataEndMarker:
//there was some data before the end of the expected DataElement serialization
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected data before marker DataEndMarker: {foundMarkerName}", dataList);
return foundMarker;
case MessageConstants.DataInfoStartMarker:
case MessageConstants.MessageEndMarker:
case MessageConstants.ReportStartMarker:
case MessageConstants.ReportEndMarker:
case MessageConstants.VariableLengthStartMarker:
case MessageConstants.VariableLengthEndMarker:
case MessageConstants.DataInfoEndMarker:
case MessageConstants.AttributeStartMarker:
case MessageConstants.AttributeEndMarker:
case MessageConstants.MessageStartMarker:
MessageReader.LogErrorDataElement(ref errorDetected, $"Unexpected marker found before DataEndMarker: {foundMarkerName}", dataList);
break;
default:
MessageReader.LogErrorDataElement(ref errorDetected, "No recognizeable marker found or end of stream reached while looking for DataEndMarker", dataList);
return foundMarker;
}
}
}
}
}