diff --git a/src/box/memtx_rtree.cc b/src/box/memtx_rtree.cc index b6f0be027e5d04cad3e3a33e2fe0c36af160fe8e..6a6bc037e723004651b53ebbf08cdb45d1380891 100644 --- a/src/box/memtx_rtree.cc +++ b/src/box/memtx_rtree.cc @@ -29,14 +29,15 @@ #include "memtx_rtree.h" #include "tuple.h" #include "space.h" +#include "memtx_engine.h" #include "errinj.h" #include "fiber.h" #include "small/small.h" -/** For all memory used by all rtree indexes. */ -static struct mempool rtree_page_pool; -/** Number of allocated pages. */ -static int rtree_page_pool_initialized = 0; +/** + * Single-linked list of free rtree pages + */ +static void *rtree_free_pages = 0; /* {{{ Utilities. *************************************************/ @@ -125,17 +126,40 @@ static void * rtree_page_alloc() { ERROR_INJECT(ERRINJ_INDEX_ALLOC, return 0); - return mempool_alloc(&rtree_page_pool); + if (!rtree_free_pages) { + /** + * No free pages in list - let's allocate new extent, split it + * into pages and add them to the list. + */ + char *extent = (char *)memtx_index_extent_alloc(); + if (!extent) { + panic("%s", "Memory allocation failed in rtree"); + return 0; + } + assert(MEMTX_EXTENT_SIZE % RTREE_PAGE_SIZE == 0); + assert(RTREE_PAGE_SIZE >= sizeof(void *)); + for (size_t i = 0; i < MEMTX_EXTENT_SIZE; i += RTREE_PAGE_SIZE) { + *(void **)(extent + i) = rtree_free_pages; + rtree_free_pages = (void *)(extent + i); + } + } + /* Now we surely have a free page in free list */ + void *res = rtree_free_pages; + rtree_free_pages = *(void **)rtree_free_pages; + return res; } static void rtree_page_free(void *page) { - return mempool_free(&rtree_page_pool, page); + /* Just add to free list. */ + *(void **)page = rtree_free_pages; + rtree_free_pages = page; } + MemtxRTree::~MemtxRTree() { - // Iterator has to be destroye prior to tree + // Iterator has to be destroyed prior to tree if (m_position != NULL) { index_rtree_iterator_free(m_position); m_position = NULL; @@ -150,11 +174,7 @@ MemtxRTree::MemtxRTree(struct key_def *key_def) assert(key_def->parts[0].type = ARRAY); assert(key_def->is_unique == false); - if (rtree_page_pool_initialized == 0) { - mempool_create(&rtree_page_pool, &cord()->slabc, - RTREE_PAGE_SIZE); - rtree_page_pool_initialized = 1; - } + memtx_index_arena_init(); rtree_init(&tree, rtree_page_alloc, rtree_page_free); } diff --git a/test/box/rtree_errinj.test.lua b/test/box/rtree_errinj.test.lua new file mode 100644 index 0000000000000000000000000000000000000000..05844364ed5bc125d334f3b22c87aa49f723893f --- /dev/null +++ b/test/box/rtree_errinj.test.lua @@ -0,0 +1,20 @@ +errinj = require('box.error.injection') + +s = box.schema.create_space('spatial') + +s:create_index('primary') +s:create_index('spatial', { type = 'rtree', unique = false, parts = {2, 'array'}}) + +errinj.set("ERRINJ_INDEX_ALLOC", true) +s:insert{1,{0,0}} +s:insert{2,{0,10}} +s:insert{3,{0,50}} +s:insert{4,{10,0}} +s:insert{5,{50,0}} +s:insert{6,{10,10}} +s:insert{7,{10,50}} +s:insert{8,{50,10}} +s:insert{9,{50,50}} +errinj.set("ERRINJ_INDEX_ALLOC", false) + +s:drop() diff --git a/test/box/suite.ini b/test/box/suite.ini index 807422123594320de65c110e9f2e8bebdbc5291e..f2c8a406efff50512b77c7e3caac825842ac5aa2 100644 --- a/test/box/suite.ini +++ b/test/box/suite.ini @@ -2,8 +2,8 @@ core = tarantool description = tarantool/box, minimal configuration script = box.lua -disabled = +disabled = rtree_errinj.test.lua valgrind_disabled = admin_coredump.test.lua -release_disabled = errinj.test.lua errinj_index.test.lua cmdline.test.lua +release_disabled = errinj.test.lua errinj_index.test.lua rtree_errinj.test.lua cmdline.test.lua lua_libs = lua/fiber.lua lua/fifo.lua use_unix_sockets = True