~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_alloc.c

Fixed sql_builtin.cc.in... stupid generated files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
 
 
16
 
/**
17
 
 * @file
18
 
 * Routines to handle mallocing of results which will be freed the same time 
19
 
 */
20
 
 
21
 
#include "config.h"
22
 
 
23
 
#include "drizzled/internal/my_sys.h"
24
 
#include "drizzled/internal/m_string.h"
25
 
 
26
 
#include <algorithm>
27
 
 
28
 
using namespace std;
29
 
 
30
 
namespace drizzled
31
 
{
32
 
 
33
 
static const unsigned int MAX_BLOCK_TO_DROP= 4096;
34
 
static const unsigned int MAX_BLOCK_USAGE_BEFORE_DROP= 10;
35
 
 
36
 
/**
37
 
 * @brief
38
 
 * Initialize memory root
39
 
 *
40
 
 * @details
41
 
 * This function prepares memory root for further use, sets initial size of
42
 
 * chunk for memory allocation and pre-allocates first block if specified.
43
 
 * Altough error can happen during execution of this function if
44
 
 * pre_alloc_size is non-0 it won't be reported. Instead it will be
45
 
 * reported as error in first alloc_root() on this memory root.
46
 
 *
47
 
 * @param  mem_root       memory root to initialize
48
 
 * @param  block_size     size of chunks (blocks) used for memory allocation
49
 
 *                       (It is external size of chunk i.e. it should include
50
 
 *                      memory required for internal structures, thus it
51
 
 *                      should be no less than memory::ROOT_MIN_BLOCK_SIZE)
52
 
 *
53
 
 */
54
 
void memory::Root::init_alloc_root(size_t block_size_arg)
55
 
{
56
 
  free= used= pre_alloc= 0;
57
 
  min_malloc= 32;
58
 
  block_size= block_size_arg - memory::ROOT_MIN_BLOCK_SIZE;
59
 
  error_handler= 0;
60
 
  block_num= 4;                 /* We shift this with >>2 */
61
 
  first_block_usage= 0;
62
 
}
63
 
 
64
 
memory::Root::~Root()
65
 
{
66
 
}
67
 
 
68
 
 
69
 
/**
70
 
 * @details
71
 
 * Function aligns and assigns new value to block size; then it tries to
72
 
 * reuse one of existing blocks as prealloc block, or malloc new one of
73
 
 * requested size. If no blocks can be reused, all unused blocks are freed
74
 
 * before allocation.
75
 
 *
76
 
 * @param  mem_root        memory root to change defaults of
77
 
 * @param  block_size      new value of block size. Must be greater or equal
78
 
 *                         than ALLOC_ROOT_MIN_BLOCK_SIZE (this value is about
79
 
 *                         68 bytes and depends on platform and compilation flags)
80
 
 * @param pre_alloc_size  new size of preallocated block. If not zero,
81
 
 *                        must be equal to or greater than block size,
82
 
 *                        otherwise means 'no prealloc'.
83
 
 */
84
 
void memory::Root::reset_root_defaults(size_t block_size_arg, size_t pre_alloc_size)
85
 
{
86
 
  block_size= block_size_arg - memory::ROOT_MIN_BLOCK_SIZE;
87
 
  if (pre_alloc_size)
88
 
  {
89
 
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
90
 
    if (not pre_alloc || pre_alloc->size != size)
91
 
    {
92
 
      memory::internal::UsedMemory *mem, **prev= &this->free;
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/* Routines to handle mallocing of results which will be freed the same time */
 
17
 
 
18
#include <my_global.h>
 
19
#include <my_sys.h>
 
20
#include <mystrings/m_string.h>
 
21
#undef EXTRA_DEBUG
 
22
#define EXTRA_DEBUG
 
23
 
 
24
 
 
25
/*
 
26
  Initialize memory root
 
27
 
 
28
  SYNOPSIS
 
29
    init_alloc_root()
 
30
      mem_root       - memory root to initialize
 
31
      block_size     - size of chunks (blocks) used for memory allocation
 
32
                       (It is external size of chunk i.e. it should include
 
33
                        memory required for internal structures, thus it
 
34
                        should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE)
 
35
      pre_alloc_size - if non-0, then size of block that should be
 
36
                       pre-allocated during memory root initialization.
 
37
 
 
38
  DESCRIPTION
 
39
    This function prepares memory root for further use, sets initial size of
 
40
    chunk for memory allocation and pre-allocates first block if specified.
 
41
    Altough error can happen during execution of this function if
 
42
    pre_alloc_size is non-0 it won't be reported. Instead it will be
 
43
    reported as error in first alloc_root() on this memory root.
 
44
*/
 
45
 
 
46
void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
 
47
                     size_t pre_alloc_size __attribute__((unused)))
 
48
{
 
49
  mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
 
50
  mem_root->min_malloc= 32;
 
51
  mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
 
52
  mem_root->error_handler= 0;
 
53
  mem_root->block_num= 4;                       /* We shift this with >>2 */
 
54
  mem_root->first_block_usage= 0;
 
55
 
 
56
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
 
57
  if (pre_alloc_size)
 
58
  {
 
59
    if ((mem_root->free= mem_root->pre_alloc=
 
60
         (USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)),
 
61
                               MYF(0))))
 
62
    {
 
63
      mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM));
 
64
      mem_root->free->left= pre_alloc_size;
 
65
      mem_root->free->next= 0;
 
66
    }
 
67
  }
 
68
#endif
 
69
  return;
 
70
}
 
71
 
 
72
 
 
73
/*
 
74
  SYNOPSIS
 
75
    reset_root_defaults()
 
76
    mem_root        memory root to change defaults of
 
77
    block_size      new value of block size. Must be greater or equal
 
78
                    than ALLOC_ROOT_MIN_BLOCK_SIZE (this value is about
 
79
                    68 bytes and depends on platform and compilation flags)
 
80
    pre_alloc_size  new size of preallocated block. If not zero,
 
81
                    must be equal to or greater than block size,
 
82
                    otherwise means 'no prealloc'.
 
83
  DESCRIPTION
 
84
    Function aligns and assigns new value to block size; then it tries to
 
85
    reuse one of existing blocks as prealloc block, or malloc new one of
 
86
    requested size. If no blocks can be reused, all unused blocks are freed
 
87
    before allocation.
 
88
*/
 
89
 
 
90
void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
 
91
                         size_t pre_alloc_size __attribute__((unused)))
 
92
{
 
93
  assert(alloc_root_inited(mem_root));
 
94
 
 
95
  mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
 
96
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
 
97
  if (pre_alloc_size)
 
98
  {
 
99
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM));
 
100
    if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size)
 
101
    {
 
102
      USED_MEM *mem, **prev= &mem_root->free;
93
103
      /*
94
104
        Free unused blocks, so that consequent calls
95
105
        to reset_root_defaults won't eat away memory.
100
110
        if (mem->size == size)
101
111
        {
102
112
          /* We found a suitable block, no need to do anything else */
103
 
          pre_alloc= mem;
 
113
          mem_root->pre_alloc= mem;
104
114
          return;
105
115
        }
106
 
        if (mem->left + ALIGN_SIZE(sizeof(memory::internal::UsedMemory)) == mem->size)
 
116
        if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size)
107
117
        {
108
118
          /* remove block from the list and free it */
109
119
          *prev= mem->next;
110
 
          std::free(mem);
 
120
          my_free(mem, MYF(0));
111
121
        }
112
122
        else
113
123
          prev= &mem->next;
114
124
      }
115
125
      /* Allocate new prealloc block and add it to the end of free list */
116
 
      if ((mem= static_cast<memory::internal::UsedMemory *>(malloc(size))))
 
126
      if ((mem= (USED_MEM *) my_malloc(size, MYF(0))))
117
127
      {
118
 
        mem->size= size;
 
128
        mem->size= size; 
119
129
        mem->left= pre_alloc_size;
120
130
        mem->next= *prev;
121
 
        *prev= pre_alloc= mem;
 
131
        *prev= mem_root->pre_alloc= mem; 
122
132
      }
123
133
      else
124
134
      {
125
 
        pre_alloc= 0;
 
135
        mem_root->pre_alloc= 0;
126
136
      }
127
137
    }
128
138
  }
129
139
  else
 
140
#endif
 
141
    mem_root->pre_alloc= 0;
 
142
}
 
143
 
 
144
 
 
145
void *alloc_root(MEM_ROOT *mem_root, size_t length)
 
146
{
 
147
#if defined(HAVE_purify) && defined(EXTRA_DEBUG)
 
148
  register USED_MEM *next;
 
149
 
 
150
  assert(alloc_root_inited(mem_root));
 
151
 
 
152
  length+=ALIGN_SIZE(sizeof(USED_MEM));
 
153
  if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR))))
130
154
  {
131
 
    pre_alloc= 0;
 
155
    if (mem_root->error_handler)
 
156
      (*mem_root->error_handler)();
 
157
    return((uchar*) 0);                 /* purecov: inspected */
132
158
  }
133
 
}
134
 
 
135
 
/**
136
 
 * @brief 
137
 
 * Allocate a chunk of memory from the Root structure provided, 
138
 
 * obtaining more memory from the heap if necessary
139
 
 *
140
 
 * @pre
141
 
 * mem_root must have been initialised via init_alloc_root()
142
 
 *
143
 
 * @param  mem_root  The memory Root to allocate from
144
 
 * @param  length    The size of the block to allocate
145
 
 *
146
 
 * @todo Would this be more suitable as a member function on the
147
 
 * Root class?
148
 
 */
149
 
void *memory::Root::alloc_root(size_t length)
150
 
{
151
 
  unsigned char* point;
152
 
  memory::internal::UsedMemory *next= NULL;
153
 
  memory::internal::UsedMemory **prev;
154
 
  assert(alloc_root_inited());
 
159
  next->next= mem_root->used;
 
160
  next->size= length;
 
161
  mem_root->used= next;
 
162
  return((uchar*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
 
163
#else
 
164
  size_t get_size, block_size;
 
165
  uchar* point;
 
166
  register USED_MEM *next= 0;
 
167
  register USED_MEM **prev;
 
168
  assert(alloc_root_inited(mem_root));
155
169
 
156
170
  length= ALIGN_SIZE(length);
157
 
  if ((*(prev= &this->free)) != NULL)
 
171
  if ((*(prev= &mem_root->free)) != NULL)
158
172
  {
159
173
    if ((*prev)->left < length &&
160
 
        this->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP &&
161
 
        (*prev)->left < MAX_BLOCK_TO_DROP)
 
174
        mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
 
175
        (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
162
176
    {
163
177
      next= *prev;
164
178
      *prev= next->next;                        /* Remove block from list */
165
 
      next->next= this->used;
166
 
      this->used= next;
167
 
      this->first_block_usage= 0;
 
179
      next->next= mem_root->used;
 
180
      mem_root->used= next;
 
181
      mem_root->first_block_usage= 0;
168
182
    }
169
183
    for (next= *prev ; next && next->left < length ; next= next->next)
170
184
      prev= &next->next;
171
185
  }
172
186
  if (! next)
173
187
  {                                             /* Time to alloc new block */
174
 
    size_t get_size, tmp_block_size;
175
 
 
176
 
    tmp_block_size= this->block_size * (this->block_num >> 2);
177
 
    get_size= length+ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
178
 
    get_size= max(get_size, tmp_block_size);
179
 
 
180
 
    if (!(next = static_cast<memory::internal::UsedMemory *>(malloc(get_size))))
 
188
    block_size= mem_root->block_size * (mem_root->block_num >> 2);
 
189
    get_size= length+ALIGN_SIZE(sizeof(USED_MEM));
 
190
    get_size= max(get_size, block_size);
 
191
 
 
192
    if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR))))
181
193
    {
182
 
      if (this->error_handler)
183
 
        (*this->error_handler)();
184
 
      return NULL;
 
194
      if (mem_root->error_handler)
 
195
        (*mem_root->error_handler)();
 
196
      return((void*) 0);                      /* purecov: inspected */
185
197
    }
186
 
    this->block_num++;
 
198
    mem_root->block_num++;
187
199
    next->next= *prev;
188
200
    next->size= get_size;
189
 
    next->left= get_size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
201
    next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
190
202
    *prev=next;
191
203
  }
192
204
 
193
 
  point= (unsigned char*) ((char*) next+ (next->size-next->left));
194
 
  /** @todo next part may be unneeded due to this->first_block_usage counter*/
195
 
  if ((next->left-= length) < this->min_malloc)
 
205
  point= (uchar*) ((char*) next+ (next->size-next->left));
 
206
  /*TODO: next part may be unneded due to mem_root->first_block_usage counter*/
 
207
  if ((next->left-= length) < mem_root->min_malloc)
196
208
  {                                             /* Full block */
197
209
    *prev= next->next;                          /* Remove block from list */
198
 
    next->next= this->used;
199
 
    this->used= next;
200
 
    this->first_block_usage= 0;
 
210
    next->next= mem_root->used;
 
211
    mem_root->used= next;
 
212
    mem_root->first_block_usage= 0;
201
213
  }
202
 
 
203
 
  return point;
 
214
  return((void*) point);
 
215
#endif
204
216
}
205
217
 
206
218
 
207
 
/**
208
 
 * @brief
209
 
 * Allocate many pointers at the same time.
210
 
 *
211
 
 * @details
212
 
 * The variable arguments are a list of alternating pointers and lengths,
213
 
 * terminated by a null pointer:
214
 
 * @li <tt>char ** pointer1</tt>
215
 
 * @li <tt>uint length1</tt>
216
 
 * @li <tt>char ** pointer2</tt>
217
 
 * @li <tt>uint length2</tt>
218
 
 * @li <tt>...</tt>
219
 
 * @li <tt>NULL</tt>
220
 
 *
221
 
 * @c pointer1, @c pointer2 etc. all point into big allocated memory area
222
 
 *
223
 
 * @param root  Memory root
224
 
 *
225
 
 * @return
226
 
 * A pointer to the beginning of the allocated memory block in case of 
227
 
 * success or NULL if out of memory
228
 
 */
229
 
void *memory::Root::multi_alloc_root(int unused, ...)
 
219
/*
 
220
  Allocate many pointers at the same time.
 
221
 
 
222
  DESCRIPTION
 
223
    ptr1, ptr2, etc all point into big allocated memory area.
 
224
 
 
225
  SYNOPSIS
 
226
    multi_alloc_root()
 
227
      root               Memory root
 
228
      ptr1, length1      Multiple arguments terminated by a NULL pointer
 
229
      ptr2, length2      ...
 
230
      ...
 
231
      NULL
 
232
 
 
233
  RETURN VALUE
 
234
    A pointer to the beginning of the allocated memory block
 
235
    in case of success or NULL if out of memory.
 
236
*/
 
237
 
 
238
void *multi_alloc_root(MEM_ROOT *root, ...)
230
239
{
231
240
  va_list args;
232
241
  char **ptr, *start, *res;
233
242
  size_t tot_length, length;
234
243
 
235
 
  (void)unused; // For some reason Sun Studio registers unused as not used.
236
 
  va_start(args, unused);
 
244
  va_start(args, root);
237
245
  tot_length= 0;
238
246
  while ((ptr= va_arg(args, char **)))
239
247
  {
242
250
  }
243
251
  va_end(args);
244
252
 
245
 
  if (!(start= (char*) this->alloc_root(tot_length)))
246
 
    return(0);
 
253
  if (!(start= (char*) alloc_root(root, tot_length)))
 
254
    return(0);                            /* purecov: inspected */
247
255
 
248
 
  va_start(args, unused);
 
256
  va_start(args, root);
249
257
  res= start;
250
258
  while ((ptr= va_arg(args, char **)))
251
259
  {
257
265
  return((void*) start);
258
266
}
259
267
 
260
 
static void trash_mem(memory::internal::UsedMemory *)
261
 
{
262
 
  TRASH(((char*)(x) + (x->size - x->left)), x->left);
263
 
}
264
 
 
265
 
/**
266
 
 * @brief
267
 
 * Mark all data in blocks free for reusage 
268
 
 */
269
 
void memory::Root::mark_blocks_free()
270
 
{
271
 
  memory::internal::UsedMemory *next;
272
 
  memory::internal::UsedMemory **last;
 
268
#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left)
 
269
 
 
270
/* Mark all data in blocks free for reusage */
 
271
 
 
272
static inline void mark_blocks_free(MEM_ROOT* root)
 
273
{
 
274
  register USED_MEM *next;
 
275
  register USED_MEM **last;
273
276
 
274
277
  /* iterate through (partially) free blocks, mark them free */
275
 
  last= &free;
276
 
  for (next= free; next; next= *(last= &next->next))
 
278
  last= &root->free;
 
279
  for (next= root->free; next; next= *(last= &next->next))
277
280
  {
278
 
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
279
 
    trash_mem(next);
 
281
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
 
282
    TRASH_MEM(next);
280
283
  }
281
284
 
282
285
  /* Combine the free and the used list */
283
 
  *last= next= used;
 
286
  *last= next=root->used;
284
287
 
285
288
  /* now go through the used blocks and mark them free */
286
289
  for (; next; next= next->next)
287
290
  {
288
 
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
289
 
    trash_mem(next);
 
291
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
 
292
    TRASH_MEM(next);
290
293
  }
291
294
 
292
295
  /* Now everything is set; Indicate that nothing is used anymore */
293
 
  used= 0;
294
 
  first_block_usage= 0;
 
296
  root->used= 0;
 
297
  root->first_block_usage= 0;
295
298
}
296
299
 
297
 
/**
298
 
 * @brief
299
 
 * Deallocate everything used by memory::alloc_root or just move
300
 
 * used blocks to free list if called with MY_USED_TO_FREE
301
 
 *
302
 
 * @note
303
 
 * One can call this function either with root block initialised with
304
 
 * init_alloc_root() or with a zero:ed block.
305
 
 * It's also safe to call this multiple times with the same mem_root.
306
 
 *
307
 
 * @param   root     Memory root
308
 
 * @param   MyFlags  Flags for what should be freed:
309
 
 *   @li   MARK_BLOCKS_FREED    Don't free blocks, just mark them free
310
 
 *   @li   KEEP_PREALLOC        If this is not set, then free also the
311
 
 *                              preallocated block
312
 
 */
313
 
void memory::Root::free_root(myf MyFlags)
 
300
 
 
301
/*
 
302
  Deallocate everything used by alloc_root or just move
 
303
  used blocks to free list if called with MY_USED_TO_FREE
 
304
 
 
305
  SYNOPSIS
 
306
    free_root()
 
307
      root              Memory root
 
308
      MyFlags           Flags for what should be freed:
 
309
 
 
310
        MY_MARK_BLOCKS_FREED    Don't free blocks, just mark them free
 
311
        MY_KEEP_PREALLOC        If this is not set, then free also the
 
312
                                preallocated block
 
313
 
 
314
  NOTES
 
315
    One can call this function either with root block initialised with
 
316
    init_alloc_root() or with a bzero()-ed block.
 
317
    It's also safe to call this multiple times with the same mem_root.
 
318
*/
 
319
 
 
320
void free_root(MEM_ROOT *root, myf MyFlags)
314
321
{
315
 
  memory::internal::UsedMemory *next,*old;
 
322
  register USED_MEM *next,*old;
316
323
 
317
 
  if (MyFlags & memory::MARK_BLOCKS_FREE)
 
324
  if (MyFlags & MY_MARK_BLOCKS_FREE)
318
325
  {
319
 
    this->mark_blocks_free();
 
326
    mark_blocks_free(root);
320
327
    return;
321
328
  }
322
 
  if (!(MyFlags & memory::KEEP_PREALLOC))
323
 
    this->pre_alloc=0;
 
329
  if (!(MyFlags & MY_KEEP_PREALLOC))
 
330
    root->pre_alloc=0;
324
331
 
325
 
  for (next=this->used; next ;)
 
332
  for (next=root->used; next ;)
326
333
  {
327
334
    old=next; next= next->next ;
328
 
    if (old != this->pre_alloc)
329
 
      std::free(old);
 
335
    if (old != root->pre_alloc)
 
336
      my_free(old,MYF(0));
330
337
  }
331
 
  for (next=this->free ; next ;)
 
338
  for (next=root->free ; next ;)
332
339
  {
333
340
    old=next; next= next->next;
334
 
    if (old != this->pre_alloc)
335
 
      std::free(old);
336
 
  }
337
 
  this->used=this->free=0;
338
 
  if (this->pre_alloc)
339
 
  {
340
 
    this->free=this->pre_alloc;
341
 
    this->free->left=this->pre_alloc->size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
342
 
    trash_mem(this->pre_alloc);
343
 
    this->free->next=0;
344
 
  }
345
 
  this->block_num= 4;
346
 
  this->first_block_usage= 0;
347
 
}
348
 
 
349
 
/**
350
 
 * @brief
351
 
 * Duplicate a null-terminated string into memory allocated from within the
352
 
 * specified Root
353
 
 */
354
 
char *memory::Root::strdup_root(const char *str)
355
 
{
356
 
  return strmake_root(str, strlen(str));
357
 
}
358
 
 
359
 
/**
360
 
 * @brief
361
 
 * Copy the (not necessarily null-terminated) string into memory allocated
362
 
 * from within the specified Root
363
 
 *
364
 
 * @details
365
 
 * Note that the string is copied according to the length specified, so
366
 
 * null-termination is ignored. The duplicated string will be null-terminated,
367
 
 * even if the original string wasn't (one additional byte is allocated for
368
 
 * this purpose).
369
 
 */
370
 
char *memory::Root::strmake_root(const char *str, size_t len)
 
341
    if (old != root->pre_alloc)
 
342
      my_free(old,MYF(0));
 
343
  }
 
344
  root->used=root->free=0;
 
345
  if (root->pre_alloc)
 
346
  {
 
347
    root->free=root->pre_alloc;
 
348
    root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
 
349
    TRASH_MEM(root->pre_alloc);
 
350
    root->free->next=0;
 
351
  }
 
352
  root->block_num= 4;
 
353
  root->first_block_usage= 0;
 
354
  return;
 
355
}
 
356
 
 
357
/*
 
358
  Find block that contains an object and set the pre_alloc to it
 
359
*/
 
360
 
 
361
void set_prealloc_root(MEM_ROOT *root, char *ptr)
 
362
{
 
363
  USED_MEM *next;
 
364
  for (next=root->used; next ; next=next->next)
 
365
  {
 
366
    if ((char*) next <= ptr && (char*) next + next->size > ptr)
 
367
    {
 
368
      root->pre_alloc=next;
 
369
      return;
 
370
    }
 
371
  }
 
372
  for (next=root->free ; next ; next=next->next)
 
373
  {
 
374
    if ((char*) next <= ptr && (char*) next + next->size > ptr)
 
375
    {
 
376
      root->pre_alloc=next;
 
377
      return;
 
378
    }
 
379
  }
 
380
}
 
381
 
 
382
 
 
383
char *strdup_root(MEM_ROOT *root, const char *str)
 
384
{
 
385
  return strmake_root(root, str, strlen(str));
 
386
}
 
387
 
 
388
 
 
389
char *strmake_root(MEM_ROOT *root, const char *str, size_t len)
371
390
{
372
391
  char *pos;
373
 
  if ((pos= (char *)alloc_root(len+1)))
 
392
  if ((pos=alloc_root(root,len+1)))
374
393
  {
375
394
    memcpy(pos,str,len);
376
395
    pos[len]=0;
378
397
  return pos;
379
398
}
380
399
 
381
 
/**
382
 
 * @brief
383
 
 * Duplicate the provided block into memory allocated from within the specified
384
 
 * Root
385
 
 *
386
 
 * @return
387
 
 * non-NULL pointer to a copy of the data if memory could be allocated, otherwise
388
 
 * NULL
389
 
 */
390
 
void *memory::Root::memdup_root(const void *str, size_t len)
 
400
 
 
401
void *memdup_root(MEM_ROOT *root, const void *str, size_t len)
391
402
{
392
 
  void *pos;
393
 
 
394
 
  if ((pos= this->alloc_root(len)))
 
403
  char *pos;
 
404
  if ((pos=alloc_root(root,len)))
395
405
    memcpy(pos,str,len);
396
 
 
397
406
  return pos;
398
407
}
399
 
 
400
 
} /* namespace drizzled */