/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
FWStorage/TFileAdaptor/src/ReadRepacker.cc
152 строки
5 KB
Chris Jones
Moved IOPool/TFileAdaptor to FWStorage sub-system
10 дек 2025, 17:51
10 дек 2025, 17:51
560058c
Код
Авторство
О чём код?
#include <cassert> #include <cstring> #include "ReadRepacker.h" /** Given a list of offsets and positions, pack them into a vector of IOPosBuffer (an "IO Vector"). This function will coalesce reads that are within READ_COALESCE_SIZE into a IOPosBuffer. This function will not create an IO vector whose summed buffer size is larger than TEMPORARY_BUFFER_SIZE. The IOPosBuffer in iov all point to a location inside buf. @param pos: An array of file offsets, nbuf long. @param len: An array of offset length, nbuf long. @param nbuf: Number of buffers to pack. @param buf: Location of temporary buffer for the results of the storage request. @param buffer_size: Size of the temporary buffer. Returns the number of entries of the original array packed into iov. */ int ReadRepacker::pack(long long int *pos, int *len, int nbuf, char *buf, IOSize buffer_size) { reset(nbuf); m_len = len; // Record the len array so we can later unpack. // Determine the buffer to use for the initial packing. char *tmp_buf; IOSize tmp_size; if (buffer_size < TEMPORARY_BUFFER_SIZE) { m_spare_buffer.resize(TEMPORARY_BUFFER_SIZE); tmp_buf = m_spare_buffer.data(); tmp_size = TEMPORARY_BUFFER_SIZE; } else { tmp_buf = buf; tmp_size = buffer_size; } int pack_count = packInternal(pos, len, nbuf, tmp_buf, tmp_size); if ((nbuf - pack_count > 0) && // If there is remaining work.. (tmp_buf != m_spare_buffer.data()) && // and the spare buffer isn't already used ((IOSize)len[pack_count] < TEMPORARY_BUFFER_SIZE)) { // And the spare buffer is big enough to hold at least one read. // Verify the spare is allocated. // If tmp_buf != &m_spare_buffer[0] before, it certainly won't after. m_spare_buffer.resize(TEMPORARY_BUFFER_SIZE); // If there are remaining chunks and we aren't already using the spare // buffer, try using that too. // This clutters up the code badly, but could save a network round-trip. pack_count += packInternal( &pos[pack_count], &len[pack_count], nbuf - pack_count, m_spare_buffer.data(), TEMPORARY_BUFFER_SIZE); } return pack_count; } int ReadRepacker::packInternal(long long int *pos, int *len, int nbuf, char *buf, IOSize buffer_size) { if (nbuf == 0) { return 0; } // Handle case 1 separately to make the for-loop cleaner. int iopb_offset = m_iov.size(); // Because we re-use the buffer from ROOT, we are guarantee this iopb will // fit. assert(static_cast<IOSize>(len[0]) <= buffer_size); IOPosBuffer iopb(pos[0], buf, len[0]); m_idx_to_iopb.push_back(iopb_offset); m_idx_to_iopb_offset.push_back(0); IOSize buffer_used = len[0]; int idx = 1; for (; idx < nbuf; idx++) { if (buffer_used + len[idx] > buffer_size) { // No way we can include this chunk in the read buffer break; } edm::storage::IOOffset extra_bytes_signed = (idx == 0) ? 0 : ((pos[idx] - iopb.offset()) - iopb.size()); assert(extra_bytes_signed >= 0); IOSize extra_bytes = static_cast<IOSize>(extra_bytes_signed); if (((static_cast<IOSize>(len[idx]) < BIG_READ_SIZE) || (iopb.size() < BIG_READ_SIZE)) && (extra_bytes < READ_COALESCE_SIZE) && (buffer_used + len[idx] + extra_bytes <= buffer_size)) { // The space between the two reads is small enough we can coalesce. // We enforce that the current read or the current iopb must be small. // This is so we can "perfectly pack" buffers consisting of only big // reads - in such a case, read coalescing doesn't help much. m_idx_to_iopb.push_back(iopb_offset); m_idx_to_iopb_offset.push_back(pos[idx] - iopb.offset()); iopb.set_size(pos[idx] + len[idx] - iopb.offset()); buffer_used += (len[idx] + extra_bytes); m_extra_bytes += extra_bytes; continue; } // There is a big jump, but still space left in the temporary buffer. // Record our current iopb: m_iov.push_back(iopb); // Reset iopb iopb.set_offset(pos[idx]); iopb.set_data(buf + buffer_used); iopb.set_size(len[idx]); // Record location of this chunk. iopb_offset++; m_idx_to_iopb.push_back(iopb_offset); m_idx_to_iopb_offset.push_back(0); buffer_used += len[idx]; } m_iov.push_back(iopb); m_buffer_used += buffer_used; return idx; } /** * Unpack the optimized set of reads from the storage system and copy the * results in the order ROOT requested. */ void ReadRepacker::unpack(char *buf) { char *root_result_ptr = buf; int nbuf = m_idx_to_iopb.size(); for (int idx = 0; idx < nbuf; idx++) { int iov_idx = m_idx_to_iopb[idx]; IOPosBuffer &iopb = m_iov[iov_idx]; int iopb_offset = m_idx_to_iopb_offset[idx]; char *io_result_ptr = static_cast<char *>(iopb.data()) + iopb_offset; // Note that we use the input buffer as a temporary where possible. // Hence, the source and destination can overlap; use memmove instead of memcpy. memmove(root_result_ptr, io_result_ptr, m_len[idx]); root_result_ptr += m_len[idx]; } } void ReadRepacker::reset(unsigned int nbuf) { m_extra_bytes = 0; m_buffer_used = 0; // Number of buffers to storage typically decreases, but nbuf/2 is just an // somewhat-informed guess. m_iov.reserve(nbuf / 2); m_iov.clear(); m_idx_to_iopb.reserve(nbuf); m_idx_to_iopb.clear(); m_idx_to_iopb_offset.reserve(nbuf); m_idx_to_iopb_offset.clear(); }