363 lines
8.9 KiB
C++
363 lines
8.9 KiB
C++
#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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|