]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - parser/pool_memory.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / parser / pool_memory.c
1 /* -*-pgsql-c-*- */
2 /*
3  * $Header: /cvsroot/pgpool/pgpool-II/parser/pool_memory.c,v 1.10 2008/01/29 01:56:39 y-asaba Exp $
4  *
5  * pgpool: a language independent connection pool server for PostgreSQL 
6  * written by Tatsuo Ishii
7  *
8  * Copyright (c) 2003-2008      PgPool Global Development Group
9  *
10  * Permission to use, copy, modify, and distribute this software and
11  * its documentation for any purpose and without fee is hereby
12  * granted, provided that the above copyright notice appear in all
13  * copies and that both that copyright notice and this permission
14  * notice appear in supporting documentation, and that the name of the
15  * author not be used in advertising or publicity pertaining to
16  * distribution of the software without specific, written prior
17  * permission. The author makes no representations about the
18  * suitability of this software for any purpose.  It is provided "as
19  * is" without express or implied warranty.
20  *
21  * pool_memory.c: Memory pooling module for SQL parser.
22  *
23  */
24
25 #include "pool.h"
26 #include "pool_memory.h"
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #define ALIGN 3
32 #define POOL_HEADER_SIZE (sizeof (POOL_CHUNK_HEADER))
33
34 POOL_MEMORY_POOL *pool_memory = NULL;
35
36 static int get_free_index(unsigned int size);
37
38 static int get_free_index(unsigned int size)
39 {
40         int idx = 0;
41
42         if (size > 0)
43         {
44                 size = (size - 1) >> ALIGN;
45                 while (size)
46                 {
47                         size >>= 1;
48                         idx++;
49                 }
50         }
51         return idx;
52 }
53
54 /*
55  * pool_memory_alloc:
56  *     Returns pointer to allocated memory of given size.
57  */
58 void *pool_memory_alloc(POOL_MEMORY_POOL *pool, unsigned int size)
59 {
60         POOL_BLOCK *block;
61         POOL_CHUNK *chunk;
62
63         if ((size + POOL_HEADER_SIZE) > pool->blocksize)
64         {
65                 block = malloc(sizeof(POOL_BLOCK));
66                 if (block == NULL)
67                 {
68                         pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
69                         child_exit(1);
70                 }
71                 block->allocsize = block->size = size + POOL_HEADER_SIZE;
72                 block->block = malloc(size + POOL_HEADER_SIZE);
73                 if (block->block == NULL)
74                 {
75                         pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
76                         child_exit(1);
77                 }
78                 block->freepoint = block + (size + POOL_HEADER_SIZE);
79                 chunk = block->block;
80                 chunk->header.size = size + POOL_HEADER_SIZE;
81                 block->next = pool->largeblocks;
82                 pool->largeblocks = block;
83         }
84         else
85         {
86                 int fidx = get_free_index(size + POOL_HEADER_SIZE);
87                 int allocsize = 1 << (fidx + ALIGN);
88
89                 /* pick up from freelist */
90                 if (pool->freelist[fidx] != NULL)
91                 {
92                         chunk = pool->freelist[fidx];
93                         pool->freelist[fidx] = chunk->header.next;
94                         chunk->header.size = allocsize;
95                         return chunk->data;
96                 }
97                 
98                 block = pool->blocks;
99                 if (block == NULL ||
100                         block->freepoint + allocsize > block->block + block->size)
101                 {
102                         block = malloc(sizeof(POOL_BLOCK));
103                         if (block == NULL)
104                         {
105                                 pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
106                                 child_exit(1);
107                         }
108                         block->size = pool->blocksize;
109                         block->allocsize = 0;
110                         block->block = malloc(pool->blocksize);
111                         if (block->block == NULL)
112                         {
113                                 pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
114                                 child_exit(1);
115                         }
116                         block->freepoint = block->block;
117                         block->next = pool->blocks;
118                         pool->blocks = block;
119                 }
120
121                 block = pool->blocks;
122                 chunk = block->freepoint;
123                 block->freepoint += allocsize;
124                 block->allocsize += allocsize;
125                 chunk->header.size = allocsize;
126         }
127         return chunk->data;
128 }
129
130
131 /*
132  * pool_memory_alloc_zero:
133  *     Returns pointer to allocated memory of given size.
134  *     The allocated memory is cleared.
135  */
136 void *pool_memory_alloc_zero(POOL_MEMORY_POOL *pool, unsigned int size)
137 {
138         void *ptr = pool_memory_alloc(pool, size);
139         memset(ptr, 0, size);
140         return ptr;
141 }
142
143 /*
144  * pool_memory_free:
145  *    Frees allocated memory into memory pool.
146  */
147 void pool_memory_free(POOL_MEMORY_POOL *pool, void *ptr)
148 {
149         POOL_CHUNK *chunk = ptr - POOL_HEADER_SIZE;
150         int fidx;
151
152         if (ptr == NULL)
153                 return;
154
155         if (chunk->header.size > pool->blocksize)
156         {
157                 POOL_BLOCK *block, *ptr = NULL;
158
159                 for (block = pool->largeblocks; block; ptr = block, block = block->next)
160                 {
161                         if (block->block == chunk)
162                                 break;
163                 }
164
165                 if (block == NULL)
166                 {
167                         pool_log("An adress \"%p\" does not exist in memory pool.", chunk);
168                         return;
169                 }
170
171                 if (ptr == NULL)
172                 {
173                         pool->largeblocks = block->next;
174                 }
175                 else
176                 {
177                         ptr->next = block->next;
178                 }
179                 free(block->block);
180                 free(block);
181         }
182         else
183         {
184                 fidx = get_free_index(chunk->header.size);
185                 chunk->header.next = pool->freelist[fidx];
186                 pool->freelist[fidx] = chunk;
187         }
188 }
189
190 /*
191  * pool_memory_realloc:
192  *     Returns new pointer to allocated memory of given size.
193  *     The new memory is copied from the old memory, and the old
194  *     memory is freed.
195  */
196 void *pool_memory_realloc(POOL_MEMORY_POOL *pool, void *ptr, unsigned int size)
197 {
198         int fidx;
199         void *p;
200         POOL_CHUNK *chunk = ptr - POOL_HEADER_SIZE;
201
202         if (size <= chunk->header.size - POOL_HEADER_SIZE)
203                 return ptr;
204
205         fidx = get_free_index(size + POOL_HEADER_SIZE);
206         if (size + POOL_HEADER_SIZE <= pool->blocksize &&
207                 chunk->header.size <= pool->blocksize &&
208                 fidx == get_free_index(chunk->header.size))
209         {
210                 return ptr;
211         }
212
213         p = pool_memory_alloc(pool, size);
214         memmove(p, ptr, chunk->header.size - POOL_HEADER_SIZE);
215         pool_memory_free(pool, ptr);
216
217         return p;
218 }
219
220 /*
221  * pool_memory_create:
222  *     Create a new memory pool.
223  */
224 POOL_MEMORY_POOL *pool_memory_create(int blocksize)
225 {
226         POOL_MEMORY_POOL *pool;
227         int i;
228
229         pool = malloc(sizeof(POOL_MEMORY_POOL));
230         if (pool == NULL)
231         {
232                 pool_error("pool_memory_create: malloc failed: %s", strerror(errno));
233                 child_exit(1);
234         }
235         pool->blocks = NULL;
236         pool->largeblocks = NULL;
237         pool->blocksize = blocksize;
238         
239         for (i = 0; i < SLOT_NUM; i++)
240         {
241                 pool->freelist[i] = NULL;
242         }
243
244         return pool;
245 }
246
247 /*
248  * pool_memory_delete:
249  *     Frees all memory which is allocated in the memory pool.
250  */
251 void pool_memory_delete(POOL_MEMORY_POOL *pool_memory, int reuse)
252 {
253         POOL_BLOCK *block, *ptr;
254
255         /* Reuse the first memory block */
256         if (reuse && pool_memory->blocks)
257                 block = pool_memory->blocks->next;
258         else
259                 block = pool_memory->blocks;
260
261         while (block)
262         {
263                 ptr = block->next;
264                 free(block->block);
265                 free(block);
266                 block = ptr;
267         }
268
269         for (block = pool_memory->largeblocks; block;)
270         {
271                 ptr = block->next;
272                 free(block->block);
273                 free(block);
274                 block = ptr;
275         }
276
277         if (reuse)
278         {
279                 int i;
280
281                 if (pool_memory->blocks)
282                 {
283                         pool_memory->blocks->next = NULL;
284                         pool_memory->blocks->allocsize = 0;
285                         pool_memory->blocks->freepoint = pool_memory->blocks->block;
286                 }
287                 pool_memory->largeblocks = NULL;
288                 for (i = 0; i < SLOT_NUM; i++)
289                 {
290                         pool_memory->freelist[i] = NULL;
291                 }
292         }
293         else
294         {
295                 free(pool_memory);
296                 pool_memory = NULL;
297         }
298 }
299
300 /*
301  * pool_memory_strdup:
302  *     Creates the new string which is copied the given string.
303  */
304 char *pool_memory_strdup(POOL_MEMORY_POOL *pool_memory, const char *string)
305 {
306         int len = strlen(string);
307         char *str = pool_memory_alloc(pool_memory, len + 1);
308
309         memmove(str, string, len);
310         str[len] = '\0';
311         return str;
312 }