/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ORC_BLOCK_BUFFER_HH #define ORC_BLOCK_BUFFER_HH #include "orc/MemoryPool.hh" #include namespace orc { class OutputStream; struct WriterMetrics; /** * BlockBuffer implements a memory allocation policy based on * equal-length blocks. BlockBuffer will reserve multiple blocks * for allocation. */ class BlockBuffer { private: MemoryPool& memoryPool; // current buffer size uint64_t currentSize; // maximal capacity (actual allocated memory) uint64_t currentCapacity; // unit for buffer expansion const uint64_t blockSize; // pointers to the start of each block std::vector blocks; // non-copy-constructible BlockBuffer(BlockBuffer& buffer) = delete; BlockBuffer& operator=(BlockBuffer& buffer) = delete; BlockBuffer(BlockBuffer&& buffer) = delete; BlockBuffer& operator=(BlockBuffer&& buffer) = delete; public: BlockBuffer(MemoryPool& pool, uint64_t blockSize); ~BlockBuffer(); /** * Block points to a section of memory allocated by BlockBuffer, * containing the corresponding physical memory address and available size. */ struct Block { // the start of block char* data; // number of bytes available at data uint64_t size; Block() : data(nullptr), size(0) {} Block(char* _data, uint64_t _size) : data(_data), size(_size) {} Block(const Block& block) = default; ~Block() = default; }; /** * Get the allocated block object. * The last allocated block size may be less than blockSize, * and the rest of the blocks are all of size blockSize. * @param blockIndex the index of blocks * @return the allocated block object */ Block getBlock(uint64_t blockIndex) const; /** * Get a empty block or allocate a new block to write. * If the last allocated block size is less than blockSize, * the size of empty block is equal to blockSize minus the size of * the last allocated block size. Otherwise, the size of * the empty block is equal to blockSize. * @return a empty block object */ Block getNextBlock(); /** * Get the number of blocks that are fully or partially occupied */ uint64_t getBlockNumber() const { return (currentSize + blockSize - 1) / blockSize; } uint64_t size() const { return currentSize; } uint64_t capacity() const { return currentCapacity; } void resize(uint64_t size); /** * Requests the BlockBuffer to contain at least newCapacity bytes. * Reallocation happens if there is need of more space. * @param newCapacity new capacity of BlockBuffer */ void reserve(uint64_t newCapacity); /** * Write the BlockBuffer content into OutputStream * @param output the output stream to write to * @param metrics the metrics of the writer */ void writeTo(OutputStream* output, WriterMetrics* metrics); }; } // namespace orc #endif