#include "boost/pool/pool_alloc.hpp"
/// Структура для хранения всех значений параметров в логе
struct LOGRECORD
{
public:
QString name_file; ///< имя лог-файла для данной записи
QMap<bool, QString> phase; ///< название этапа полета
std::vector<PARAMVALUE, boost::fast_pool_allocator<PARAMVALUE> > params; ///< вектор параметров
public:
LOGRECORD(const boost::fast_pool_allocator<PARAMVALUE>& only_once_allocator =
boost::fast_pool_allocator<PARAMVALUE>(), size_t size = 0): name_file(""),
params(size, PARAMVALUE(), only_once_allocator) {}
LOGRECORD(const LOGRECORD& l): name_file(l.name_file), phase(l.phase),
params(l.params.size(), PARAMVALUE(), l.params.get_allocator())
{ std::copy(l.params.begin(), l.params.end(), params.begin()); }
LOGRECORD& operator=(const LOGRECORD& l);
PARAMVALUE GetLat(QVector<ParamDescr*>* descr) const;
PARAMVALUE GetLon(QVector<ParamDescr*>* descr) const;
PARAMVALUE GetDateTime(QVector<ParamDescr*>* descr) const;
PARAMVALUE GetParamValue(QVector<ParamDescr*>* descr, const std::string& name, const Suint& addr) const;
PARAMVALUE GetParamValue(QVector<ParamDescr*>* descr, const std::string& name) const;
PARAMVALUE GetParamValue(QVector<ParamDescr*>* descr, const Suint& addr, std::string& instance);
};
class LogReader: public QObject
{
Q_OBJECT
private:
QVector<uint> m_vBlock; ///< вектор прочитанных слов
QFile* _file; ///< указатель на файл загрузки (лог-файл)
char* files_buff; ///< буфер, в который будут считываться все данные из файлов
qint64 bytes_read; ///< реальное количество прочитанных данных
int records_count; ///< количество записей в лог-файле
boost::fast_pool_allocator<PARAMVALUE> alloc;///< распределитель памяти
public:
QVector<ParamDescr*> rec_descr; ///< вектор параметров из файла описания (файла загрузки)
TLV* mainWindow; ///< указатель на объект главного окна
private:
bool parseBlock(LOGRECORD& t);
void ChangeDateTime(LOGRECORD& t);
void FillCompParams(LOGRECORD& t);
void selectPhase(ParamDescr* descrParam, int index, LOGRECORD& t);
void selectPhase(LOGRECORD& t);
void fillHlpLog(const LOGRECORD& t, uint index);
void compareTimeMark(QVector<LOGRECORD>& log, time_t& before_read);
void lastCompare(QVector<LOGRECORD>& log, const time_t& before_read);
public:
LogReader(std::string FileName, TLV* main): mainWindow(main), records_count(0), _file(new QFile()),
files_buff(0), bytes_read(0) { _file -> setName(FileName.c_str()); }
LogReader(const char* FileName, TLV* main): mainWindow(main), records_count(0), _file(new QFile()),
files_buff(0), bytes_read(0) { _file -> setName(FileName); }
~LogReader() { shutdown(); }
///// ................................................... ////////
void setBytesRead(qint64 n) { bytes_read = n; }
qint64 bytesRead() const { return bytes_read; }
bool tRead();
bool parseBuffer();
};
/// Выбор этапа полета
void LogReader::selectPhase(ParamDescr* descrParam, int index, LOGRECORD& t)
{
if(descrParam -> Name() != "phaseoperation") return;
int n = t.params[index].value;
if(n < phaseList.size() && !phaseList.isEmpty())
{
t.phase[true] = phaseList[n][(mainWindow) ? mainWindow -> Language() : true];
t.phase[false] = phaseList[n][(mainWindow) ? !mainWindow -> Language() : false];
}
}
/// Выбор этапа полета - если нет совпадений имен
void LogReader::selectPhase(LOGRECORD& t)
{
if(t.phase.isEmpty() && !phaseList.isEmpty())
{
bool f = (mainWindow) ? mainWindow -> Language() : true;
t.phase[f] = phaseList[0][f];
t.phase[!f] = phaseList[0][!f];
}
}
/// Разбор одной записи
bool LogReader::parseBlock(LOGRECORD& t)
{
struct VARS {
bool flag;
uint var;
VARS(): flag(false), var(0) {}
} vars[ADDR_LIMIT];
t.name_file = strippedName(_file -> fileName());
int i = 0, block_size = m_vBlock.size();
for(int j=0; j<block_size; ++j)
{
uint index = m_vBlock[j] % ADDR_LIMIT;
vars[index].flag = true;
vars[index].var = m_vBlock[j];
}
paramI end(rec_descr.end());
for(paramI iter=rec_descr.begin(); iter!=end; ++iter, ++i)
{
uint addr_index = (*iter) -> Address();
if(addr_index < ADDR_LIMIT)
if(vars[addr_index].flag)
t.params[i] = (*iter) -> GetValue(vars[addr_index].var);
selectPhase((*iter), i, t);
}
selectPhase(t);
return true;
}
/// Заполнение вычислимых параметров
void LogReader::FillCompParams(LOGRECORD& t)
{
if(mainWindow -> iniReader() -> indexComputeParam() < 0) return;
for(int i=mainWindow -> iniReader() -> indexComputeParam(); i<rec_descr.size(); ++i)
{
CompParamDescr* p = dynamic_cast<CompParamDescr*> (rec_descr[i]);
ElemFormul formul(p -> formulList());
COMPUTE* element = formul.calculateFormul(&t, &rec_descr);
if(element != 0)
{
t.params[i].value = element -> GetValue();
t.params[i].status = PS_OK;
t.params[i].evn = 0;
}
}
}
/// Заполнение вектора-получателя частями прочитанных данных
void LogReader::fillVec(QVector<LOGRECORD>& sender) { mainWindow -> addData(sender); }
/// Запись значений времени и даты
void LogReader::ChangeDateTime(LOGRECORD& t)
{
int time_index = mainWindow -> iniReader() -> indexTimeParam(),
date_index = mainWindow -> iniReader() -> indexDateParam();
TimeParamDescr* dt_time = dynamic_cast<TimeParamDescr*> (rec_descr[time_index]);
DateParamDescr* dt_date = dynamic_cast<DateParamDescr*> (rec_descr[date_index]);
tm c_time = dt_time -> TCTime(), c_date = dt_date -> TCDate();
TimeDateParamDescr tmd(c_time, c_date);
t.params[time_index] = tmd.GetValue(0);
t.params[date_index] = tmd.GetValue(0);
}
/// Заполнение hlp_log
void LogReader::fillHlpLog(const LOGRECORD& t, uint index)
{
if(index == 0)
mainWindow -> hlp_log.append(VEC_PARTNER(index, t.name_file, t.phase));
else if(index > 0 && mainWindow -> hlp_log.size() != 0)
{
if(mainWindow -> hlp_log.last().name != t.name_file ||
mainWindow -> hlp_log.last().phase != t.phase)
mainWindow -> hlp_log.append(VEC_PARTNER(index, t.name_file, t.phase));
}
}
/// Сравнение временных меток
void LogReader::compareTimeMark(QVector<LOGRECORD>& log, time_t& before_read)
{
time_t contin_read;
time(&contin_read);
time_t delta = contin_read - before_read;
if(delta > 2)
{
before_read = contin_read;
fillVec(log);
log.clear();
}
}
/// Сравнение временных меток, если чтение файла завершилось раньше, чем через 3 секунды
void LogReader::lastCompare(QVector<LOGRECORD>& log, const time_t& before_read)
{
if(!log.size()) return;
fillVec(log);
log.clear();
}
/// Чтение файла загрузки
bool LogReader::tRead()
{
if(!open()) return false; ///< открываем файл с логом
if(_file -> size() > FBUFF_SIZE - bytes_read)
return false;
qint64 really_read = _file -> read(&files_buff[bytes_read], _file -> size());
assert(really_read == _file -> size());
bytes_read += really_read;
shutdown(); ///< закрываем файл с логом
return true;
}
/// Разбор прочитанного буфера
bool LogReader::parseBuffer()
{
uint var = 1e+6, index = 0;
int i = 0;
bool bBlock = false, buff_ready = false;
LOGRECORD unit(alloc, rec_descr.size());
QVector<LOGRECORD> log(0, unit);
time_t before_read; time(&before_read);
for(uint* p=reinterpret_cast<uint*>(files_buff); i<(bytes_read / sizeof(var)); ++p, ++i)
{
var = *p;
Suint adr = var % 256;
/// Определение начала/конца одной записи и записывание ее в вектор
switch(adr)
{
case 0000:
m_vBlock.clear();
bBlock = true;
break;
case 0001:
if(bBlock)
{
log.append(unit);
parseBlock(log.last());
ChangeDateTime(log.last());
if(mainWindow -> iniReader() -> indexComputeParam() > 0)
FillCompParams(log.last());
fillHlpLog(log.last(), index);
buff_ready = true;
compareTimeMark(log, before_read);
++index;
}
bBlock = false;
break;
default:
if(bBlock) m_vBlock.append((uint)var);
}
}
lastCompare(log, before_read);
return buff_ready;
}