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