MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/logging/StorageManager.cpp
2024-06-07 11:12:56 +03:00

363 lines
9.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "LoggingExcept.hh"
#include "StorageManager.hh"
namespace logging {
StorageManager::StorageManager( peripheral::IMemoryAccess & _memory, std::pmr::memory_resource & _allocator, bool _auto_sync ) :
memory(_memory), mem_op_exec(_memory), allocator(&_allocator), feedback_load_block( &*this, &StorageManager::on_load_block, allocator),
feedback_write_bckt(&*this, &StorageManager::on_write_block, allocator), blocks_limit((memory.getCapacity() - sizeof(ControlBlock)) / block_size()),
block_write_op(NOPE), block_load_op(NO_LOAD), auto_cache_sync(_auto_sync),
buffer_in_ready(false), feedback_init_backet( &*this, &StorageManager::on_init_backet, allocator ), finish_commit( true ) {
if( not blocks_limit )
throw out_of_range(blocks_limit); //Смысла нет при нулевом значении.
if( auto_cache_sync )
sync_timer.start(sync_buffer_period);
load_control_block();
}
bool StorageManager::commit( const char * data, size_t length ) {
bool append = true;
if( !finish_commit )
return false;
if( length > buffer_in.allowed_space() )
throw max_allowed_size(length);
if( not buffer_in_ready )
return false;
/*
** Заполняем буфер и двигаем указатель до тех пор, пока может поместиться сообщение.
** В случае заполнения, передаем его на запись в долговременную память.
*/
if( not drop_buffer_to_storage && buffer_in.free_space() >= length ) {
buffer_in.fill(data, length);
buffer_in.update_crc();
information_block_is_dirty = true;
} else {
append = false;
drop_buffer_to_storage = true;
}
return append;
}
std::pair<StorageManager::PrefetchResult, StorageReadInterface::DataBlock> StorageManager::prefetch_block( BlockId block_id ) {
PrefetchResult result = IDLE_STATE;
if( block_id >= blocks_count() ) {
result = OUT_OF_BOUND;
} else if( block_load_op == logging::StorageManager::NO_LOAD and fetch_parameters.block != block_id ) {
fetch_parameters.block = block_id;
fetch_parameters.result = IN_PROGRESS;
result = IN_PROGRESS;
load_block( block_id );
} else {
result = fetch_parameters.result;
if( result == COMPLETE ) {
fetch_parameters.result = IDLE_STATE;
fetch_parameters.block = -1;
}
}
return { result, buffer_out.data() };
}
StorageReadInterface::DataBlock StorageManager::read_buffered_block() {
return buffer_out.serialize();
}
void StorageManager::read_block_async( size_t, prefetch_result &, const char *, size_t & ) {}
void StorageManager::process() {
if( block_write_op == NOPE ) {
if( drop_buffer_to_storage ) {
mux_block_operation(INSERT_AND_MOVE);
} else if( auto_cache_sync && sync_timer.delayElapsed() && information_block_is_dirty ) {
mux_block_operation(SYNC);
}
}
mem_op_exec.process();
}
void StorageManager::get_block_hash_async( size_t, prefetch_result & , uint32_t & ) {}
size_t StorageManager::blocks_count() {
return blocks_limit;
}
size_t StorageManager::allocated_bytes() {
return memory.getCapacity();
}
size_t StorageManager::block_size() {
return buffer_in.size();
}
void StorageManager::set_cache_synchronize_period( unsigned long long _period ) {
sync_buffer_period = _period;
sync_timer.start(sync_buffer_period);
}
void StorageManager::flush_local() {
buffer_in.reset();
buffer_out.reset();
}
void StorageManager::on_load_block( MemoryOperationExecutor::OPERATION_RESULT res ) {
//Если все прошло успешно, то тогда мы пытаемся проверить заголовок.
if( res == MemoryOperationExecutor::DONE ) {
switch (block_load_op) {
case logging::StorageManager::LOAD_CONTROL: {
uint32_t s_crc = common::crc::crcCalc<common::crc::Crc32_ZLIB>(
reinterpret_cast<char*>(&control_block),
sizeof(ControlBlock) - sizeof(control_block.check_summ)
);
bool eql_crc = s_crc == control_block.check_summ;
bool eql_mgk_k = control_block.magick_key == MAGICK_KEY;
bool eql_bckt_s = buffer_in.size() == control_block.bucket_size;
bool coursor_in_range = control_block.coursor <= blocks_limit;
if( not(eql_crc && eql_mgk_k && eql_bckt_s && coursor_in_range) ) {
control_block.magick_key = MAGICK_KEY;
control_block.bucket_size = buffer_in.size();
control_block.coursor = 0x0;
control_block.check_summ = common::crc::crcCalc<common::crc::Crc32_ZLIB>(
reinterpret_cast<char*>(&control_block),
sizeof(ControlBlock) - sizeof(control_block.check_summ)
);
//reset backet:
buffer_in.reset();
buffer_in_ready = true;
} else {
control_block.number_of_power_on += 1;
init_backet();
}
sync_control_block();
} break;
case logging::StorageManager::LOAD_INFO: {
if( not buffer_out.check() )
buffer_out.reset();
fetch_parameters.result = COMPLETE;
} break;
default: {
throw logic_error();
} break;
}
block_load_op = logging::StorageManager::NO_LOAD;
}
}
/* Асинхронная подгрузка информационного заголовка в оперативную память.*/
void StorageManager::load_control_block() {
if( mem_op_exec.execute_task(
MemoryOperationExecutor::READ_OP,
reinterpret_cast<char*>(&control_block),
INFOHEADER_BASE, sizeof(ControlBlock),
&feedback_load_block) )
block_load_op = logging::StorageManager::LOAD_CONTROL;
}
/* Синхронизировать блок управления в оперативной памяти и ПЗУ. */
void StorageManager::sync_control_block() {
mem_op_exec.execute_task(
MemoryOperationExecutor::WRITE_OP,
reinterpret_cast<char*>(&control_block),
INFOHEADER_BASE, sizeof(ControlBlock),
nullptr );
}
void StorageManager::mux_block_operation( BLOCK_WRITE_OPERATION action ) {
block_write_op = action;
send_block();
}
void StorageManager::on_write_block( MemoryOperationExecutor::OPERATION_RESULT res ) {
sync_timer.start(sync_buffer_period);
information_block_is_dirty = false;
drop_buffer_to_storage = false;
switch (block_write_op) {
case logging::StorageManager::SYNC: {} break;
case logging::StorageManager::INSERT_AND_MOVE: {
buffer_in.reset();
control_block.coursor = (control_block.coursor + 1) >= blocks_count() ? 0 : control_block.coursor + 1;
control_block.check_summ = common::crc::crcCalc<common::crc::Crc32_ZLIB>(reinterpret_cast<char*>(&control_block), sizeof(ControlBlock) - sizeof(control_block.check_summ));
sync_control_block();
} break;
default: {
throw logic_error();
} break;
}
block_write_op = NOPE;
}
void StorageManager::send_block() {
finish_commit = false;
std::pair<const char *, size_t> sp = buffer_in.serialize();
finish_commit = true;
mem_op_exec.execute_task(
MemoryOperationExecutor::WRITE_OP,
sp.first,
in_memory_placement(control_block.coursor), sp.second,
&feedback_write_bckt );
}
void StorageManager::load_block( BlockId block_id ) {
std::pair<const char*, size_t> sp = buffer_out.serialize();
if( mem_op_exec.execute_task(
MemoryOperationExecutor::READ_OP,
sp.first,
in_memory_placement(block_id), sp.second,
&feedback_load_block ) )
block_load_op = logging::StorageManager::LOAD_INFO;
}
size_t StorageManager::in_memory_placement( BlockId block_id ) {
size_t place = sizeof(ControlBlock);
if( block_id < blocks_limit )
place += block_id * buffer_in.size();
else
throw out_of_range( block_id );
return place;
}
void StorageManager::on_init_backet(
MemoryOperationExecutor::OPERATION_RESULT res) {
if( res == MemoryOperationExecutor::DONE ) {
if( not buffer_in.check() )
buffer_in.reset();
buffer_in_ready = true;
}
block_load_op = logging::StorageManager::NO_LOAD;
}
void StorageManager::init_backet() {
std::pair<const char*, size_t> sp = buffer_in.serialize();
if( mem_op_exec.execute_task(
MemoryOperationExecutor::READ_OP,
sp.first,
in_memory_placement( control_block.coursor ), sp.second,
&feedback_init_backet ) )
block_load_op = logging::StorageManager::INIT_BACKET;
}
StorageManager::PowerOnNumber StorageManager::power_on() const {
return control_block.number_of_power_on;
}
bool StorageManager::storage_ready() const {
return buffer_in_ready;
}
}