| 530 | |
| 531 | template<typename Key, typename Engine> |
| 532 | void PersistentTableImpl<Key, Engine>::Put(uint32_t num_keys, const void* keys, |
| 533 | const void* values) { |
| 534 | CHECK(!read_only_); |
| 535 | std::lock_guard<std::recursive_mutex> lock(mutex_); |
| 536 | const void* blocks_ptr = nullptr; |
| 537 | if (value_size_ == logical_block_size_ |
| 538 | && reinterpret_cast<uintptr_t>(values) % physical_block_size_ == 0) { |
| 539 | blocks_ptr = values; |
| 540 | } else { |
| 541 | const uint32_t num_blocks = RoundUp(num_keys, num_values_per_block_); |
| 542 | blocks_buffer_.Resize(num_blocks * logical_block_size_); |
| 543 | for (uint32_t i = 0; i < num_keys; i += num_values_per_block_) { |
| 544 | const uint32_t block_id = i / num_values_per_block_; |
| 545 | const uint32_t copy_size = (num_keys - i) < num_values_per_block_ |
| 546 | ? (num_keys - i) * value_size_ |
| 547 | : logical_block_size_; |
| 548 | MemcpyOffset(blocks_buffer_.ptr(), block_id * logical_block_size_, values, i * value_size_, |
| 549 | copy_size); |
| 550 | } |
| 551 | blocks_ptr = blocks_buffer_.ptr(); |
| 552 | } |
| 553 | PutBlocks(num_keys, keys, blocks_ptr); |
| 554 | } |
| 555 | |
| 556 | template<typename Key, typename Engine> |
| 557 | std::string PersistentTableImpl<Key, Engine>::KeyFilePath(uint64_t chunk_id) const { |