| 775 | } |
| 776 | |
| 777 | void commitMessages(Reference<LogData> self, |
| 778 | Version version, |
| 779 | Arena arena, |
| 780 | StringRef messages, |
| 781 | VectorRef<OldTagMessagesRef> tags, |
| 782 | int64_t& bytesInput) { |
| 783 | // SOMEDAY: This method of copying messages is reasonably memory efficient, but it's still a lot of bytes copied. |
| 784 | // Find a way to do the memory allocation right as we receive the messages in the network layer. |
| 785 | |
| 786 | int64_t addedBytes = 0; |
| 787 | int64_t expectedBytes = 0; |
| 788 | |
| 789 | if (!messages.size()) { |
| 790 | return; |
| 791 | } |
| 792 | |
| 793 | StringRef messages1; // the first block of messages, if they aren't all stored contiguously. otherwise empty |
| 794 | |
| 795 | // Grab the last block in the blocks list so we can share its arena |
| 796 | // We pop all of the elements of it to create a "fresh" vector that starts at the end of the previous vector |
| 797 | Standalone<VectorRef<uint8_t>> block; |
| 798 | if (self->messageBlocks.empty()) { |
| 799 | block = Standalone<VectorRef<uint8_t>>(); |
| 800 | block.reserve(block.arena(), std::max<int64_t>(SERVER_KNOBS->TLOG_MESSAGE_BLOCK_BYTES, messages.size())); |
| 801 | } else { |
| 802 | block = self->messageBlocks.back().second; |
| 803 | } |
| 804 | |
| 805 | block.pop_front(block.size()); |
| 806 | |
| 807 | // If the current batch of messages doesn't fit entirely in the remainder of the last block in the list |
| 808 | if (messages.size() + block.size() > block.capacity()) { |
| 809 | // Find how many messages will fit |
| 810 | LengthPrefixedStringRef r((uint32_t*)messages.begin()); |
| 811 | uint8_t const* end = messages.begin() + block.capacity() - block.size(); |
| 812 | while (r.toStringRef().end() <= end) { |
| 813 | r = LengthPrefixedStringRef((uint32_t*)r.toStringRef().end()); |
| 814 | } |
| 815 | |
| 816 | // Fill up the rest of this block |
| 817 | int bytes = (uint8_t*)r.getLengthPtr() - messages.begin(); |
| 818 | if (bytes) { |
| 819 | CODE_PROBE(true, "Splitting commit messages across multiple blocks"); |
| 820 | messages1 = StringRef(block.end(), bytes); |
| 821 | block.append(block.arena(), messages.begin(), bytes); |
| 822 | self->messageBlocks.emplace_back(version, block); |
| 823 | addedBytes += int64_t(block.size()) * SERVER_KNOBS->TLOG_MESSAGE_BLOCK_OVERHEAD_FACTOR; |
| 824 | messages = messages.substr(bytes); |
| 825 | } |
| 826 | |
| 827 | // Make a new block |
| 828 | block = Standalone<VectorRef<uint8_t>>(); |
| 829 | block.reserve(block.arena(), std::max<int64_t>(SERVER_KNOBS->TLOG_MESSAGE_BLOCK_BYTES, messages.size())); |
| 830 | } |
| 831 | |
| 832 | // Copy messages into block |
| 833 | ASSERT(messages.size() <= block.capacity() - block.size()); |
| 834 | block.append(block.arena(), messages.begin(), messages.size()); |
no test coverage detected