~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
16
/**
17
 * @file
18
 * Routines to handle mallocing of results which will be freed the same time 
19
 */
1 by brian
clean slate
20
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
21
#include <config.h>
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
22
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
23
#include <drizzled/internal/my_sys.h>
24
#include <drizzled/internal/m_string.h>
1 by brian
clean slate
25
1067.4.10 by Nathan Williams
Converted all cmin/cmax usages in the mysys directory to std::min/max.
26
#include <algorithm>
27
28
using namespace std;
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
29
30
namespace drizzled
31
{
1 by brian
clean slate
32
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
33
static const unsigned int MAX_BLOCK_TO_DROP= 4096;
34
static const unsigned int MAX_BLOCK_USAGE_BEFORE_DROP= 10;
35
1441.2.1 by Tim Martin
Reformatting some memory/root.h comments for doxygen
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
 */
1487 by Brian Aker
More updates for memory::Root
54
void memory::Root::init_alloc_root(size_t block_size_arg)
1 by brian
clean slate
55
{
1487 by Brian Aker
More updates for memory::Root
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;
1 by brian
clean slate
62
}
63
1869.1.7 by Brian Aker
Cleanup of caller to ha_open().
64
memory::Root::~Root()
65
{
66
}
67
1 by brian
clean slate
68
1441.2.1 by Tim Martin
Reformatting some memory/root.h comments for doxygen
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
 */
1485 by Brian Aker
Updates to confine memroot
84
void memory::Root::reset_root_defaults(size_t block_size_arg, size_t pre_alloc_size)
1 by brian
clean slate
85
{
1485 by Brian Aker
Updates to confine memroot
86
  block_size= block_size_arg - memory::ROOT_MIN_BLOCK_SIZE;
1 by brian
clean slate
87
  if (pre_alloc_size)
88
  {
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
89
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
1485 by Brian Aker
Updates to confine memroot
90
    if (not pre_alloc || pre_alloc->size != size)
1 by brian
clean slate
91
    {
1485 by Brian Aker
Updates to confine memroot
92
      memory::internal::UsedMemory *mem, **prev= &this->free;
1 by brian
clean slate
93
      /*
94
        Free unused blocks, so that consequent calls
95
        to reset_root_defaults won't eat away memory.
96
      */
97
      while (*prev)
98
      {
99
        mem= *prev;
100
        if (mem->size == size)
101
        {
102
          /* We found a suitable block, no need to do anything else */
1485 by Brian Aker
Updates to confine memroot
103
          pre_alloc= mem;
1 by brian
clean slate
104
          return;
105
        }
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
106
        if (mem->left + ALIGN_SIZE(sizeof(memory::internal::UsedMemory)) == mem->size)
1 by brian
clean slate
107
        {
108
          /* remove block from the list and free it */
109
          *prev= mem->next;
1485 by Brian Aker
Updates to confine memroot
110
          std::free(mem);
1 by brian
clean slate
111
        }
112
        else
113
          prev= &mem->next;
114
      }
115
      /* Allocate new prealloc block and add it to the end of free list */
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
116
      if ((mem= static_cast<memory::internal::UsedMemory *>(malloc(size))))
1 by brian
clean slate
117
      {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
118
        mem->size= size;
1 by brian
clean slate
119
        mem->left= pre_alloc_size;
120
        mem->next= *prev;
1485 by Brian Aker
Updates to confine memroot
121
        *prev= pre_alloc= mem;
1 by brian
clean slate
122
      }
123
      else
124
      {
1485 by Brian Aker
Updates to confine memroot
125
        pre_alloc= 0;
1 by brian
clean slate
126
      }
127
    }
128
  }
129
  else
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
130
  {
1485 by Brian Aker
Updates to confine memroot
131
    pre_alloc= 0;
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
132
  }
1 by brian
clean slate
133
}
134
1441.2.5 by Tim Martin
More doxygen commenting
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
 */
1485 by Brian Aker
Updates to confine memroot
149
void *memory::Root::alloc_root(size_t length)
150
{
481 by Brian Aker
Remove all of uchar.
151
  unsigned char* point;
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
152
  memory::internal::UsedMemory *next= NULL;
153
  memory::internal::UsedMemory **prev;
1487 by Brian Aker
More updates for memory::Root
154
  assert(alloc_root_inited());
1 by brian
clean slate
155
156
  length= ALIGN_SIZE(length);
1486 by Brian Aker
More encapsulation.
157
  if ((*(prev= &this->free)) != NULL)
1 by brian
clean slate
158
  {
159
    if ((*prev)->left < length &&
1486 by Brian Aker
More encapsulation.
160
	this->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP &&
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
161
	(*prev)->left < MAX_BLOCK_TO_DROP)
1 by brian
clean slate
162
    {
163
      next= *prev;
164
      *prev= next->next;			/* Remove block from list */
1486 by Brian Aker
More encapsulation.
165
      next->next= this->used;
166
      this->used= next;
167
      this->first_block_usage= 0;
1 by brian
clean slate
168
    }
169
    for (next= *prev ; next && next->left < length ; next= next->next)
170
      prev= &next->next;
171
  }
172
  if (! next)
173
  {						/* Time to alloc new block */
1486 by Brian Aker
More encapsulation.
174
    size_t get_size, tmp_block_size;
175
176
    tmp_block_size= this->block_size * (this->block_num >> 2);
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
177
    get_size= length+ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
1486 by Brian Aker
More encapsulation.
178
    get_size= max(get_size, tmp_block_size);
1 by brian
clean slate
179
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
180
    if (!(next = static_cast<memory::internal::UsedMemory *>(malloc(get_size))))
1 by brian
clean slate
181
    {
1486 by Brian Aker
More encapsulation.
182
      if (this->error_handler)
183
	(*this->error_handler)();
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
184
      return NULL;
1 by brian
clean slate
185
    }
1486 by Brian Aker
More encapsulation.
186
    this->block_num++;
1 by brian
clean slate
187
    next->next= *prev;
188
    next->size= get_size;
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
189
    next->left= get_size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
1 by brian
clean slate
190
    *prev=next;
191
  }
192
481 by Brian Aker
Remove all of uchar.
193
  point= (unsigned char*) ((char*) next+ (next->size-next->left));
1486 by Brian Aker
More encapsulation.
194
  /** @todo next part may be unneeded due to this->first_block_usage counter*/
195
  if ((next->left-= length) < this->min_malloc)
1 by brian
clean slate
196
  {						/* Full block */
197
    *prev= next->next;				/* Remove block from list */
1486 by Brian Aker
More encapsulation.
198
    next->next= this->used;
199
    this->used= next;
200
    this->first_block_usage= 0;
1 by brian
clean slate
201
  }
1441.2.5 by Tim Martin
More doxygen commenting
202
203
  return point;
1 by brian
clean slate
204
}
205
206
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
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
 */
1532.1.7 by Brian Aker
Fix for non-portable vastart usage.
229
void *memory::Root::multi_alloc_root(int unused, ...)
1 by brian
clean slate
230
{
231
  va_list args;
232
  char **ptr, *start, *res;
233
  size_t tot_length, length;
234
1532.1.9 by Brian Aker
Fix for Solaris build issue.
235
  (void)unused; // For some reason Sun Studio registers unused as not used.
1532.1.7 by Brian Aker
Fix for non-portable vastart usage.
236
  va_start(args, unused);
1 by brian
clean slate
237
  tot_length= 0;
238
  while ((ptr= va_arg(args, char **)))
239
  {
240
    length= va_arg(args, uint);
241
    tot_length+= ALIGN_SIZE(length);
242
  }
243
  va_end(args);
244
1532.1.5 by Brian Aker
Shift the varargs so that they are a part of memory::Root
245
  if (!(start= (char*) this->alloc_root(tot_length)))
971.6.11 by Eric Day
Removed purecov messages.
246
    return(0);
1 by brian
clean slate
247
1532.1.7 by Brian Aker
Fix for non-portable vastart usage.
248
  va_start(args, unused);
1 by brian
clean slate
249
  res= start;
250
  while ((ptr= va_arg(args, char **)))
251
  {
252
    *ptr= res;
253
    length= va_arg(args, uint);
254
    res+= ALIGN_SIZE(length);
255
  }
256
  va_end(args);
51.3.20 by Jay Pipes
Phase 6 - Remove DBUG from mysys
257
  return((void*) start);
1 by brian
clean slate
258
}
259
2151.2.5 by Olaf van der Spek
Replace TRASH_MEM macro by function
260
static void trash_mem(memory::internal::UsedMemory *)
261
{
262
  TRASH(((char*)(x) + (x->size - x->left)), x->left);
263
}
1 by brian
clean slate
264
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
265
/**
266
 * @brief
267
 * Mark all data in blocks free for reusage 
1441.2.5 by Tim Martin
More doxygen commenting
268
 */
1485 by Brian Aker
Updates to confine memroot
269
void memory::Root::mark_blocks_free()
1 by brian
clean slate
270
{
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
271
  memory::internal::UsedMemory *next;
272
  memory::internal::UsedMemory **last;
1 by brian
clean slate
273
274
  /* iterate through (partially) free blocks, mark them free */
1485 by Brian Aker
Updates to confine memroot
275
  last= &free;
276
  for (next= free; next; next= *(last= &next->next))
1 by brian
clean slate
277
  {
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
278
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
2151.2.5 by Olaf van der Spek
Replace TRASH_MEM macro by function
279
    trash_mem(next);
1 by brian
clean slate
280
  }
281
282
  /* Combine the free and the used list */
1485 by Brian Aker
Updates to confine memroot
283
  *last= next= used;
1 by brian
clean slate
284
285
  /* now go through the used blocks and mark them free */
286
  for (; next; next= next->next)
287
  {
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
288
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
2151.2.5 by Olaf van der Spek
Replace TRASH_MEM macro by function
289
    trash_mem(next);
1 by brian
clean slate
290
  }
291
292
  /* Now everything is set; Indicate that nothing is used anymore */
1485 by Brian Aker
Updates to confine memroot
293
  used= 0;
294
  first_block_usage= 0;
1 by brian
clean slate
295
}
296
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
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
 */
1487 by Brian Aker
More updates for memory::Root
313
void memory::Root::free_root(myf MyFlags)
1 by brian
clean slate
314
{
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
315
  memory::internal::UsedMemory *next,*old;
1 by brian
clean slate
316
1253.1.1 by Monty Taylor
First bits of namespacing. Ugh. Why do I do this to myself.
317
  if (MyFlags & memory::MARK_BLOCKS_FREE)
1 by brian
clean slate
318
  {
1487 by Brian Aker
More updates for memory::Root
319
    this->mark_blocks_free();
51.3.20 by Jay Pipes
Phase 6 - Remove DBUG from mysys
320
    return;
1 by brian
clean slate
321
  }
1253.1.1 by Monty Taylor
First bits of namespacing. Ugh. Why do I do this to myself.
322
  if (!(MyFlags & memory::KEEP_PREALLOC))
1487 by Brian Aker
More updates for memory::Root
323
    this->pre_alloc=0;
1 by brian
clean slate
324
1487 by Brian Aker
More updates for memory::Root
325
  for (next=this->used; next ;)
1 by brian
clean slate
326
  {
327
    old=next; next= next->next ;
1487 by Brian Aker
More updates for memory::Root
328
    if (old != this->pre_alloc)
329
      std::free(old);
1 by brian
clean slate
330
  }
1487 by Brian Aker
More updates for memory::Root
331
  for (next=this->free ; next ;)
1 by brian
clean slate
332
  {
333
    old=next; next= next->next;
1487 by Brian Aker
More updates for memory::Root
334
    if (old != this->pre_alloc)
335
      std::free(old);
1 by brian
clean slate
336
  }
1487 by Brian Aker
More updates for memory::Root
337
  this->used=this->free=0;
338
  if (this->pre_alloc)
1 by brian
clean slate
339
  {
1487 by Brian Aker
More updates for memory::Root
340
    this->free=this->pre_alloc;
341
    this->free->left=this->pre_alloc->size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
2151.2.5 by Olaf van der Spek
Replace TRASH_MEM macro by function
342
    trash_mem(this->pre_alloc);
1487 by Brian Aker
More updates for memory::Root
343
    this->free->next=0;
1 by brian
clean slate
344
  }
1487 by Brian Aker
More updates for memory::Root
345
  this->block_num= 4;
346
  this->first_block_usage= 0;
1 by brian
clean slate
347
}
348
1441.2.5 by Tim Martin
More doxygen commenting
349
/**
350
 * @brief
351
 * Duplicate a null-terminated string into memory allocated from within the
352
 * specified Root
353
 */
1487 by Brian Aker
More updates for memory::Root
354
char *memory::Root::strdup_root(const char *str)
1 by brian
clean slate
355
{
1487 by Brian Aker
More updates for memory::Root
356
  return strmake_root(str, strlen(str));
1 by brian
clean slate
357
}
358
1441.2.5 by Tim Martin
More doxygen commenting
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
 */
1487 by Brian Aker
More updates for memory::Root
370
char *memory::Root::strmake_root(const char *str, size_t len)
1 by brian
clean slate
371
{
372
  char *pos;
1487 by Brian Aker
More updates for memory::Root
373
  if ((pos= (char *)alloc_root(len+1)))
1 by brian
clean slate
374
  {
375
    memcpy(pos,str,len);
376
    pos[len]=0;
377
  }
378
  return pos;
379
}
380
1441.2.5 by Tim Martin
More doxygen commenting
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
 */
1487 by Brian Aker
More updates for memory::Root
390
void *memory::Root::memdup_root(const void *str, size_t len)
1 by brian
clean slate
391
{
575.3.1 by Monty Taylor
Made mysys and mystrings c++. Fixed the resulting bugs the compiler found.
392
  void *pos;
1487 by Brian Aker
More updates for memory::Root
393
394
  if ((pos= this->alloc_root(len)))
1 by brian
clean slate
395
    memcpy(pos,str,len);
1487 by Brian Aker
More updates for memory::Root
396
1 by brian
clean slate
397
  return pos;
398
}
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
399
400
} /* namespace drizzled */