Beispiel #1
0
void IOBuf::unshareOneSlow() {
  // Allocate a new buffer for the data
  uint8_t* buf;
  SharedInfo* sharedInfo;
  uint64_t actualCapacity;
  allocExtBuffer(capacity_, &buf, &sharedInfo, &actualCapacity);

  // Copy the data
  // Maintain the same amount of headroom.  Since we maintained the same
  // minimum capacity we also maintain at least the same amount of tailroom.
  uint64_t headlen = headroom();
  if (length_ > 0) {
    assert(data_ != nullptr);
    memcpy(buf + headlen, data_, length_);
  }

  // Release our reference on the old buffer
  decrementRefcount();
  // Make sure kFlagMaybeShared and kFlagFreeSharedInfo are all cleared.
  setFlagsAndSharedInfo(0, sharedInfo);

  // Update the buffer pointers to point to the new buffer
  data_ = buf + headlen;
  buf_ = buf;
}
Beispiel #2
0
IOBuf::IOBuf(CreateOp, uint32_t capacity)
  : next_(this),
    prev_(this),
    data_(nullptr),
    length_(0),
    flags_(0),
    type_(kExtAllocated) {
  allocExtBuffer(capacity, &buf_, &sharedInfo_, &capacity_);
  data_ = buf_;
}
Beispiel #3
0
IOBuf::IOBuf(CreateOp, uint64_t capacity)
  : next_(this),
    prev_(this),
    data_(nullptr),
    length_(0),
    flagsAndSharedInfo_(0) {
  SharedInfo* info;
  allocExtBuffer(capacity, &buf_, &info, &capacity_);
  setSharedInfo(info);
  data_ = buf_;
}
Beispiel #4
0
void IOBuf::coalesceAndReallocate(size_t newHeadroom,
                                  size_t newLength,
                                  IOBuf* end,
                                  size_t newTailroom) {
  uint64_t newCapacity = newLength + newHeadroom + newTailroom;
  if (newCapacity > UINT32_MAX) {
    throw std::overflow_error("IOBuf chain too large to coalesce");
  }

  // Allocate space for the coalesced buffer.
  // We always convert to an external buffer, even if we happened to be an
  // internal buffer before.
  uint8_t* newBuf;
  SharedInfo* newInfo;
  uint32_t actualCapacity;
  allocExtBuffer(newCapacity, &newBuf, &newInfo, &actualCapacity);

  // Copy the data into the new buffer
  uint8_t* newData = newBuf + newHeadroom;
  uint8_t* p = newData;
  IOBuf* current = this;
  size_t remaining = newLength;
  do {
    assert(current->length_ <= remaining);
    remaining -= current->length_;
    memcpy(p, current->data_, current->length_);
    p += current->length_;
    current = current->next_;
  } while (current != end);
  assert(remaining == 0);

  // Point at the new buffer
  decrementRefcount();

  // Make sure kFlagUserOwned, kFlagMaybeShared, and kFlagFreeSharedInfo
  // are all cleared.
  flags_ = 0;

  capacity_ = actualCapacity;
  type_ = kExtAllocated;
  buf_ = newBuf;
  sharedInfo_ = newInfo;
  data_ = newData;
  length_ = newLength;

  // Separate from the rest of our chain.
  // Since we don't store the unique_ptr returned by separateChain(),
  // this will immediately delete the returned subchain.
  if (isChained()) {
    (void)separateChain(next_, current->prev_);
  }
}
Beispiel #5
0
void IOBuf::coalesceAndReallocate(size_t newHeadroom,
                                  size_t newLength,
                                  IOBuf* end,
                                  size_t newTailroom) {
  uint64_t newCapacity = newLength + newHeadroom + newTailroom;

  // Allocate space for the coalesced buffer.
  // We always convert to an external buffer, even if we happened to be an
  // internal buffer before.
  uint8_t* newBuf;
  SharedInfo* newInfo;
  uint64_t actualCapacity;
  allocExtBuffer(newCapacity, &newBuf, &newInfo, &actualCapacity);

  // Copy the data into the new buffer
  uint8_t* newData = newBuf + newHeadroom;
  uint8_t* p = newData;
  IOBuf* current = this;
  size_t remaining = newLength;
  do {
    if (current->length_ > 0) {
      assert(current->length_ <= remaining);
      assert(current->data_ != nullptr);
      remaining -= current->length_;
      memcpy(p, current->data_, current->length_);
      p += current->length_;
    }
    current = current->next_;
  } while (current != end);
  assert(remaining == 0);

  // Point at the new buffer
  decrementRefcount();

  // Make sure kFlagMaybeShared and kFlagFreeSharedInfo are all cleared.
  setFlagsAndSharedInfo(0, newInfo);

  capacity_ = actualCapacity;
  buf_ = newBuf;
  data_ = newData;
  length_ = newLength;

  // Separate from the rest of our chain.
  // Since we don't store the unique_ptr returned by separateChain(),
  // this will immediately delete the returned subchain.
  if (isChained()) {
    (void)separateChain(next_, current->prev_);
  }
}
Beispiel #6
0
void IOBuf::unshareOneSlow() {
  // Allocate a new buffer for the data
  uint8_t* buf;
  SharedInfo* sharedInfo;
  uint32_t actualCapacity;
  allocExtBuffer(capacity_, &buf, &sharedInfo, &actualCapacity);

  // Copy the data
  // Maintain the same amount of headroom.  Since we maintained the same
  // minimum capacity we also maintain at least the same amount of tailroom.
  uint32_t headlen = headroom();
  memcpy(buf + headlen, data_, length_);

  // Release our reference on the old buffer
  decrementRefcount();
  // Make sure kFlagUserOwned, kFlagMaybeShared, and kFlagFreeSharedInfo
  // are all cleared.
  flags_ = 0;

  // Update the buffer pointers to point to the new buffer
  data_ = buf + headlen;
  buf_ = buf;
  sharedInfo_ = sharedInfo;
}