1 /*
2  Copyright (c) 2004-2012 NFG Net Facilities Group BV support@nfg.nl
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the GNU General Public License
6  as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later
8  version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 #include "dbmail.h"
21 #include "dm_mempool.h"
22 #include "mpool/mpool.h"
23 
24 #define THIS_MODULE "mempool"
25 
26 #define M Mempool_T
27 
28 #define fail_unless(a) assert(a)
29 
30 struct M {
31 	pthread_mutex_t lock;
32 	mpool_t *pool;
33 };
34 
mempool_open(void)35 M mempool_open(void)
36 {
37 	M MP;
38 	mpool_t *pool = NULL;
39 	static gboolean env_mpool = false;
40 	static gboolean use_mpool = false;
41 
42 	if (! env_mpool) {
43 		char *dm_pool = getenv("DM_POOL");
44 		if (MATCH(dm_pool, "yes"))
45 			use_mpool = true;
46 		env_mpool = true;
47 	}
48 	if (use_mpool)
49 		pool = mpool_open(0,0,0,NULL);
50 	else
51 		pool = NULL;
52 
53 	MP = mpool_alloc(pool, sizeof(*MP), NULL);
54 
55 	if (pthread_mutex_init(&MP->lock, NULL)) {
56 		perror("pthread_mutex_init failed");
57 		mpool_free(pool, MP, sizeof(*MP));
58 		if (pool)
59 			mpool_close(pool);
60 		return NULL;
61 	}
62 
63 	MP->pool = pool;
64 	return MP;
65 }
66 
mempool_pop(M MP,size_t blocksize)67 void * mempool_pop(M MP, size_t blocksize)
68 {
69 	int error;
70 	PLOCK(MP->lock);
71 	void *block = mpool_calloc(MP->pool, 1, blocksize, &error);
72 	PUNLOCK(MP->lock);
73 	if (error != MPOOL_ERROR_NONE)
74 		TRACE(TRACE_ERR, "%s", mpool_strerror(error));
75 	return block;
76 }
77 
mempool_resize(M MP,void * block,size_t oldsize,size_t newsize)78 void * mempool_resize(M MP, void *block, size_t oldsize, size_t newsize)
79 {
80 	int error;
81 	PLOCK(MP->lock);
82 	void *newblock = mpool_resize(MP->pool, block, oldsize, newsize, &error);
83 	PUNLOCK(MP->lock);
84 	if (error != MPOOL_ERROR_NONE)
85 		TRACE(TRACE_ERR, "%s", mpool_strerror(error));
86 	assert (error == MPOOL_ERROR_NONE);
87 	return newblock;
88 }
89 
mempool_push(M MP,void * block,size_t blocksize)90 void mempool_push(M MP, void *block, size_t blocksize)
91 {
92 	int error;
93 	PLOCK(MP->lock);
94 	if ((error = mpool_free(MP->pool, block, blocksize)) != MPOOL_ERROR_NONE)
95 		TRACE(TRACE_ERR, "%s", mpool_strerror(error));
96 
97 	fail_unless(error == MPOOL_ERROR_NONE);
98 	PUNLOCK(MP->lock);
99 }
100 
mempool_stats(M MP)101 void mempool_stats(M MP)
102 {
103 	unsigned int page_size;
104         unsigned long num_alloced, user_alloced, max_alloced, tot_alloced;
105 	mpool_stats(MP->pool, &page_size, &num_alloced, &user_alloced,
106 			&max_alloced, &tot_alloced);
107 	TRACE(TRACE_DEBUG, "[%p] page_size: %u num: %" PRIu64 " user: %" PRIu64 " "
108 			"max: %" PRIu64 " tot: %" PRIu64 "", MP->pool,
109 			page_size, (uint64_t)num_alloced, (uint64_t)user_alloced,
110 			(uint64_t)max_alloced, (uint64_t)tot_alloced);
111 }
112 
mempool_close(M * MP)113 void mempool_close(M *MP)
114 {
115 	int error;
116 	M mp = *MP;
117 	pthread_mutex_t lock = mp->lock;
118 	PLOCK(lock);
119 	mpool_t *pool = mp->pool;
120 	if (pool) {
121 		mempool_stats(mp);
122 		if ((error = mpool_close(pool)) != MPOOL_ERROR_NONE)
123 			TRACE(TRACE_ERR, "%s", mpool_strerror(error));
124 	} else {
125 		free(mp);
126 	}
127 	PUNLOCK(lock);
128 	pthread_mutex_destroy(&lock);
129 	mp = NULL;
130 }
131 
132 #undef M
133