MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/logging/StorageManager.cpp

363 lines
8.9 KiB
C++
Raw Permalink Normal View History

#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); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
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;
/*
** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
** <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
*/
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 ) {
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
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;
}
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.*/
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;
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD>. */
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;
}
}