| 444 | |
| 445 | template<typename Key, typename Engine> |
| 446 | void PersistentTableImpl<Key, Engine>::Get(uint32_t num_keys, const void* keys, void* values, |
| 447 | uint32_t* n_missing, uint32_t* missing_indices) { |
| 448 | std::lock_guard<std::recursive_mutex> lock(mutex_); |
| 449 | offsets_buffer_.resize(num_keys); |
| 450 | void* blocks_ptr = nullptr; |
| 451 | if (value_size_ == logical_block_size_ |
| 452 | && reinterpret_cast<uintptr_t>(values) % physical_block_size_ == 0) { |
| 453 | blocks_ptr = values; |
| 454 | } else { |
| 455 | blocks_buffer_.Resize(num_keys * logical_block_size_); |
| 456 | blocks_ptr = blocks_buffer_.ptr(); |
| 457 | } |
| 458 | GetBlocks(num_keys, keys, blocks_ptr, offsets_buffer_.data()); |
| 459 | uint32_t missing_count = 0; |
| 460 | for (uint32_t i = 0; i < num_keys; ++i) { |
| 461 | if (offsets_buffer_.at(i) == logical_block_size_) { |
| 462 | missing_indices[missing_count] = i; |
| 463 | missing_count += 1; |
| 464 | } else { |
| 465 | if (value_size_ != logical_block_size_) { |
| 466 | MemcpyOffset(values, i * value_size_, blocks_ptr, |
| 467 | (i * logical_block_size_) + offsets_buffer_[i], value_size_); |
| 468 | } |
| 469 | } |
| 470 | } |
| 471 | *n_missing = missing_count; |
| 472 | } |
| 473 | |
| 474 | template<typename Key, typename Engine> |
| 475 | void PersistentTableImpl<Key, Engine>::PutBlocks(uint32_t num_keys, const void* keys, |