in src/native/diffs/core/slicer.cpp [42:137]
void slicer::request_slice(std::shared_ptr<prepared_item> &to_slice, uint64_t offset, const item_definition &slice)
{
// we shouldn't be trying to slice hashes out of a thing
// when we don't know the hash and can't verify it
if (!slice.has_any_hashes())
{
throw errors::user_exception(
errors::error_code::diff_slicing_request_slice_no_hash, "Trying to hash item with no hash.");
}
// printf("slicer::request_slice() for: %s\n", slice.to_string().c_str());
std::lock_guard<std::mutex> state_lock_guard{m_state_mutex};
if (m_state != slicing_state::paused)
{
throw errors::user_exception(
errors::error_code::diff_slicing_invalid_state,
"slicer::request_slice: Expected slicing state to be paused, actual: " + std::to_string((int)m_state));
}
std::lock_guard<std::mutex> request_lock_guard{m_request_mutex};
// Add an entry about the request we're making
if (m_slice_item_request_counts.count(slice) != 0)
{
ADU_LOG("slicer::request_slice: Already have a request for this item: {}", slice.to_string());
// There's already a pending request for a matching slice
// make one more request and bail
m_slice_item_request_counts[slice]++;
return;
}
auto item_to_slice = to_slice->get_item_definition();
if (m_item_to_slice_prepared.count(item_to_slice) == 0)
{
m_item_to_slice_prepared.insert(std::pair{item_to_slice, to_slice});
}
if (m_items_to_slices_requested.count(item_to_slice) == 0)
{
auto new_map = std::make_unique<offset_to_item_map>();
new_map->insert(std::pair{offset, slice});
m_items_to_slices_requested.insert(std::pair{item_to_slice, std::move(new_map)});
m_slice_item_request_counts.insert(std::pair{slice, 1});
return;
}
auto &offset_to_slice_map = *(m_items_to_slices_requested[item_to_slice].get());
ADU_LOG("slicer::request_slice: Adding entry for offset: {}, for item: {}", offset, slice.to_string());
// check that we're not overlapping with the previous result
if (offset_to_slice_map.size() != 0)
{
// lower_bound is first offset that is not < offset, it is >= our offset
auto lower_bound = offset_to_slice_map.lower_bound(offset);
if (lower_bound != offset_to_slice_map.cend())
{
uint64_t lower_bound_offset = lower_bound->first;
uint64_t lower_bound_length = lower_bound->second.size();
if (!check_overlap(offset, slice.size(), lower_bound_offset, lower_bound_length))
{
std::string msg = "slicer::request_slice: Found overlap with slices. ";
msg += "offset: " + std::to_string(offset);
msg += ", length: " + std::to_string(slice.size());
msg += ", lower_bound_offset: " + std::to_string(lower_bound_offset);
msg += ", lower_bound_length: " + std::to_string(lower_bound_length);
throw errors::user_exception(errors::error_code::diff_slicing_request_slice_overlap, msg);
}
}
if (lower_bound != offset_to_slice_map.cbegin())
{
lower_bound--;
uint64_t prev_offset = lower_bound->first;
uint64_t prev_length = lower_bound->second.size();
if (!check_overlap(offset, slice.size(), prev_offset, prev_length))
{
std::string msg = "slicer::request_slice: Found overlap with slices. ";
msg += "offset: " + std::to_string(offset);
msg += ", length: " + std::to_string(slice.size());
msg += ", prev offset: " + std::to_string(prev_offset);
msg += ", prev length: " + std::to_string(prev_length);
throw errors::user_exception(errors::error_code::diff_slicing_request_slice_overlap, msg);
}
}
}
m_slice_item_request_counts.insert(std::pair{slice, 1});
offset_to_slice_map.insert(std::pair{offset, slice});
}