github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/c-deps/libroach/chunked_buffer.cc (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 #include "chunked_buffer.h" 12 #include <rocksdb/db.h> 13 #include "encoding.h" 14 15 namespace cockroach { 16 17 // Write a key/value pair to this chunkedBuffer. 18 void chunkedBuffer::Put(const rocksdb::Slice& key, const rocksdb::Slice& value) { 19 // The key and size are passed as a single little endian encoded 20 // uint64 value. Little endian to optimize for the common case of 21 // Intel CPUs. 22 const uint32_t key_size = key.size(); 23 const uint32_t val_size = value.size(); 24 const uint8_t size_buf[sizeof(uint64_t)] = { 25 uint8_t(val_size), uint8_t(val_size >> 8), uint8_t(val_size >> 16), uint8_t(val_size >> 24), 26 uint8_t(key_size), uint8_t(key_size >> 8), uint8_t(key_size >> 16), uint8_t(key_size >> 24), 27 }; 28 put((const char*)size_buf, sizeof(size_buf), key.size() + value.size()); 29 put(key.data(), key.size(), value.size()); 30 put(value.data(), value.size(), 0); 31 count_++; 32 bytes_ += sizeof(size_buf) + key.size() + value.size(); // see (*pebbleResults).put 33 } 34 35 void chunkedBuffer::Clear() { 36 for (int i = 0; i < bufs_.size(); i++) { 37 delete[] bufs_[i].data; 38 } 39 count_ = 0; 40 bytes_ = 0; 41 buf_ptr_ = nullptr; 42 bufs_.clear(); 43 } 44 45 // put writes len bytes of the input data to this vector of buffers, 46 // allocating new buffers if necessary. next_size_hint can be passed to 47 // indicate that the required size of this buffer will soon be 48 // len+next_size_hint, to prevent excessive resize operations. 49 void chunkedBuffer::put(const char* data, int len, int next_size_hint) { 50 for (;;) { 51 const size_t avail = bufs_.empty() ? 0 : (bufs_.back().len - (buf_ptr_ - bufs_.back().data)); 52 if (len <= avail) { 53 break; 54 } 55 56 // If it's bigger than the last buf's capacity, we fill the last buf, 57 // allocate a new one, and write the remainder to the new one. Our new 58 // buf's size will be the next power of two past the size of the last buf 59 // that can accomodate the new data, plus a size hint if available. 60 memcpy(buf_ptr_, data, avail); 61 data += avail; 62 len -= avail; 63 64 const int max_size = 128 << 20; // 128 MB 65 size_t new_size = bufs_.empty() ? 16 : bufs_.back().len * 2; 66 for (; new_size < len + next_size_hint && new_size < max_size; new_size *= 2) { 67 } 68 if (new_size > max_size) { 69 new_size = max_size; 70 } 71 72 DBSlice new_buf; 73 new_buf.data = new char[new_size]; 74 new_buf.len = new_size; 75 bufs_.push_back(new_buf); 76 77 // Now reset so that we'll write the remainder below. 78 buf_ptr_ = new_buf.data; 79 } 80 81 memcpy(buf_ptr_, data, len); 82 buf_ptr_ += len; 83 } 84 85 } // namespace cockroach