diff options
Diffstat (limited to 'storage/tokudb/PerconaFT/util/mempool.cc')
-rw-r--r-- | storage/tokudb/PerconaFT/util/mempool.cc | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/storage/tokudb/PerconaFT/util/mempool.cc b/storage/tokudb/PerconaFT/util/mempool.cc new file mode 100644 index 00000000..b27be71c --- /dev/null +++ b/storage/tokudb/PerconaFT/util/mempool.cc @@ -0,0 +1,197 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of PerconaFT. + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + PerconaFT is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + PerconaFT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + PerconaFT is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + PerconaFT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <string.h> +#include <memory.h> +#include <toku_assert.h> +#include "mempool.h" + +/* Contract: + * Caller allocates mempool struct as convenient for caller, but memory used for data storage + * must be dynamically allocated via toku_malloc(). + * Caller dynamically allocates memory for mempool and initializes mempool by calling toku_mempool_init(). + * Once a buffer is assigned to a mempool (via toku_mempool_init()), the mempool owns it and + * is responsible for destroying it when the mempool is destroyed. + * Caller destroys mempool by calling toku_mempool_destroy(). + * + * Note, toku_mempool_init() does not allocate the memory because sometimes the caller will already have + * the memory allocated and will assign the pre-allocated memory to the mempool. + */ + +/* This is a constructor to be used when the memory for the mempool struct has been + * allocated by the caller, but no memory has yet been allocatd for the data. + */ +void toku_mempool_zero(struct mempool *mp) { + // printf("mempool_zero %p\n", mp); + memset(mp, 0, sizeof(*mp)); +} + +// TODO 4050 this is dirty, try to replace all uses of this +void toku_mempool_init(struct mempool *mp, void *base, size_t free_offset, size_t size) { + // printf("mempool_init %p %p %lu\n", mp, base, size); + paranoid_invariant(base != 0); + paranoid_invariant(size < (1U<<31)); // used to be assert(size >= 0), but changed to size_t so now let's make sure it's not more than 2GB... + paranoid_invariant(free_offset <= size); + mp->base = base; + mp->size = size; + mp->free_offset = free_offset; // address of first available memory + mp->frag_size = 0; // byte count of wasted space (formerly used, no longer used or available) +} + +/* allocate memory and construct mempool + */ +void toku_mempool_construct(struct mempool *mp, size_t data_size) { + if (data_size) { + // add 25% slack + size_t mp_size = data_size + (data_size / 4); + mp->base = toku_xmalloc_aligned(64, mp_size); + mp->size = mp_size; + mp->free_offset = 0; + mp->frag_size = 0; + } + else { + toku_mempool_zero(mp); + } +} + +void toku_mempool_reset(struct mempool *mp) { + mp->free_offset = 0; + mp->frag_size = 0; +} + +void toku_mempool_realloc_larger(struct mempool *mp, size_t data_size) { + invariant(data_size >= mp->free_offset); + + size_t mpsize = data_size + (data_size/4); // allow 1/4 room for expansion (would be wasted if read-only) + void* newmem = toku_xmalloc_aligned(64, mpsize); // allocate new buffer for mempool + memcpy(newmem, mp->base, mp->free_offset); // Copy old info + toku_free(mp->base); + mp->base = newmem; + mp->size = mpsize; +} + + +void toku_mempool_destroy(struct mempool *mp) { + // printf("mempool_destroy %p %p %lu %lu\n", mp, mp->base, mp->size, mp->frag_size); + if (mp->base) + toku_free(mp->base); + toku_mempool_zero(mp); +} + +void *toku_mempool_get_base(const struct mempool *mp) { + return mp->base; +} + +void *toku_mempool_get_pointer_from_base_and_offset(const struct mempool *mp, size_t offset) { + return reinterpret_cast<void*>(reinterpret_cast<char*>(mp->base) + offset); +} + +size_t toku_mempool_get_offset_from_pointer_and_base(const struct mempool *mp, const void* p) { + paranoid_invariant(p >= mp->base); + return reinterpret_cast<const char*>(p) - reinterpret_cast<const char*>(mp->base); +} + +size_t toku_mempool_get_size(const struct mempool *mp) { + return mp->size; +} + +size_t toku_mempool_get_frag_size(const struct mempool *mp) { + return mp->frag_size; +} + +size_t toku_mempool_get_used_size(const struct mempool *mp) { + return mp->free_offset - mp->frag_size; +} + +void* toku_mempool_get_next_free_ptr(const struct mempool *mp) { + return toku_mempool_get_pointer_from_base_and_offset(mp, mp->free_offset); +} + +size_t toku_mempool_get_offset_limit(const struct mempool *mp) { + return mp->free_offset; +} + +size_t toku_mempool_get_free_size(const struct mempool *mp) { + return mp->size - mp->free_offset; +} + +size_t toku_mempool_get_allocated_size(const struct mempool *mp) { + return mp->free_offset; +} + +void *toku_mempool_malloc(struct mempool *mp, size_t size) { + paranoid_invariant(size < (1U<<31)); + paranoid_invariant(mp->size < (1U<<31)); + paranoid_invariant(mp->free_offset < (1U<<31)); + paranoid_invariant(mp->free_offset <= mp->size); + void *vp; + if (mp->free_offset + size > mp->size) { + vp = nullptr; + } else { + vp = reinterpret_cast<char *>(mp->base) + mp->free_offset; + mp->free_offset += size; + } + paranoid_invariant(mp->free_offset <= mp->size); + paranoid_invariant(vp == 0 || toku_mempool_inrange(mp, vp, size)); + return vp; +} + +// if vp is null then we are freeing something, but not specifying what. The data won't be freed until compression is done. +void toku_mempool_mfree(struct mempool *mp, void *vp, size_t size) { + if (vp) { paranoid_invariant(toku_mempool_inrange(mp, vp, size)); } + mp->frag_size += size; + invariant(mp->frag_size <= mp->free_offset); + invariant(mp->frag_size <= mp->size); +} + + +/* get memory footprint */ +size_t toku_mempool_footprint(struct mempool *mp) { + void * base = mp->base; + size_t touched = mp->free_offset; + size_t rval = toku_memory_footprint(base, touched); + return rval; +} + +void toku_mempool_clone(const struct mempool* orig_mp, struct mempool* new_mp) { + new_mp->frag_size = orig_mp->frag_size; + new_mp->free_offset = orig_mp->free_offset; + new_mp->size = orig_mp->free_offset; // only make the cloned mempool store what is needed + new_mp->base = toku_xmalloc_aligned(64, new_mp->size); + memcpy(new_mp->base, orig_mp->base, new_mp->size); +} |