message_ex* dsn_message_parser::get_message_on_receive(int read_length, /*out*/ int& read_next) { mark_read(read_length); if (_read_buffer_occupied >= sizeof(message_header)) { int msg_sz = sizeof(message_header) + message_ex::get_body_length((char*)_read_buffer.data()); // msg done if (_read_buffer_occupied >= msg_sz) { auto msg_bb = _read_buffer.range(0, msg_sz); message_ex* msg = message_ex::create_receive_message(msg_bb); dassert(msg->is_right_header() && msg->is_right_body(false), ""); _read_buffer = _read_buffer.range(msg_sz); _read_buffer_occupied -= msg_sz; read_next = sizeof(message_header); return msg; } else { read_next = msg_sz - _read_buffer_occupied; return nullptr; } } else { read_next = sizeof(message_header) - _read_buffer_occupied; return nullptr; } }
void LogWriter::run() { while (!_exit_thread) { // Outer endless loop // Wait for _should_run flag while (!_exit_thread) { bool start = false; pthread_mutex_lock(&_mtx); pthread_cond_wait(&_cv, &_mtx); start = _should_run; pthread_mutex_unlock(&_mtx); if (start) { break; } } int poll_count = 0; int written = 0; while (true) { size_t available = 0; void *read_ptr = nullptr; bool is_part = false; /* lock _buffer * wait for sufficient data, cycle on notify() */ pthread_mutex_lock(&_mtx); while (true) { available = get_read_ptr(&read_ptr, &is_part); /* if sufficient data available or partial read or terminating, exit this wait loop */ if ((available >= _min_write_chunk) || is_part || !_should_run) { /* GOTO end of block */ break; } /* wait for a call to notify() * this call unlocks the mutex while waiting, and returns with the mutex locked */ pthread_cond_wait(&_cv, &_mtx); } pthread_mutex_unlock(&_mtx); written = 0; if (available > 0) { perf_begin(_perf_write); written = ::write(_fd, read_ptr, available); perf_end(_perf_write); /* call fsync periodically to minimize potential loss of data */ if (++poll_count >= 100) { perf_begin(_perf_fsync); ::fsync(_fd); perf_end(_perf_fsync); poll_count = 0; } if (written < 0) { PX4_WARN("error writing log file"); _should_run = false; /* GOTO end of block */ break; } pthread_mutex_lock(&_mtx); /* subtract bytes written from number in _buffer (_count -= written) */ mark_read(written); pthread_mutex_unlock(&_mtx); _total_written += written; } if (!_should_run && written == static_cast<int>(available) && !is_part) { // Stop only when all data written _running = false; _head = 0; _count = 0; if (_fd >= 0) { int res = ::close(_fd); _fd = -1; if (res) { PX4_WARN("error closing log file"); } else { PX4_INFO("closed logfile: %s, bytes written: %zu", _filename, _total_written); } } break; } } } }
message_ex* dsn_message_parser::get_message_on_receive(int read_length, /*out*/ int& read_next) { mark_read(read_length); if (_read_buffer_occupied >= sizeof(message_header)) { if (!_header_checked) { if (!message_ex::is_right_header((char*)_read_buffer.data())) { derror("receive message header check failed for message"); truncate_read(); read_next = -1; return nullptr; } else { _header_checked = true; } } int msg_sz = sizeof(message_header) + message_ex::get_body_length((char*)_read_buffer.data()); // msg done if (_read_buffer_occupied >= msg_sz) { auto msg_bb = _read_buffer.range(0, msg_sz); message_ex* msg = message_ex::create_receive_message(msg_bb); if (!msg->is_right_body(false)) { message_header* header = (message_header*)_read_buffer.data(); derror("body check failed for message, id: %d, rpc_name: %s, from: %s", header->id, header->rpc_name, header->from_address.to_string()); truncate_read(); read_next = -1; return nullptr; } else { _read_buffer = _read_buffer.range(msg_sz); _read_buffer_occupied -= msg_sz; _header_checked = false; read_next = sizeof(message_header); return msg; } } else { read_next = msg_sz - _read_buffer_occupied; return nullptr; } } else { read_next = sizeof(message_header) - _read_buffer_occupied; return nullptr; } }