~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/include/rem0rec.h

  • Committer: Brian Aker
  • Date: 2010-02-07 01:33:54 UTC
  • Revision ID: brian@gaz-20100207013354-d2pg1n68u5c09pgo
Remove giant include header to its own file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/************************************************************************
2
 
Record manager
3
 
 
4
 
(c) 1994-1996 Innobase Oy
5
 
 
6
 
Created 5/30/1994 Heikki Tuuri
7
 
*************************************************************************/
8
 
 
9
 
#ifndef rem0rec_h
10
 
#define rem0rec_h
11
 
 
12
 
#include "univ.i"
13
 
#include "data0data.h"
14
 
#include "rem0types.h"
15
 
#include "mtr0types.h"
16
 
 
17
 
/* Info bit denoting the predefined minimum record: this bit is set
18
 
if and only if the record is the first user record on a non-leaf
19
 
B-tree page that is the leftmost page on its level
20
 
(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */
21
 
#define REC_INFO_MIN_REC_FLAG   0x10UL
22
 
 
23
 
/* Number of extra bytes in an old-style record,
24
 
in addition to the data and the offsets */
25
 
#define REC_N_OLD_EXTRA_BYTES   6
26
 
/* Number of extra bytes in a new-style record,
27
 
in addition to the data and the offsets */
28
 
#define REC_N_NEW_EXTRA_BYTES   5
29
 
 
30
 
/* Record status values */
31
 
#define REC_STATUS_ORDINARY     0
32
 
#define REC_STATUS_NODE_PTR     1
33
 
#define REC_STATUS_INFIMUM      2
34
 
#define REC_STATUS_SUPREMUM     3
35
 
 
36
 
/* Number of elements that should be initially allocated for the
37
 
offsets[] array, first passed to rec_get_offsets() */
38
 
#define REC_OFFS_NORMAL_SIZE    100
39
 
#define REC_OFFS_SMALL_SIZE     10
40
 
 
41
 
/**********************************************************
42
 
The following function is used to get the offset of the
43
 
next chained record on the same page. */
44
 
UNIV_INLINE
45
 
ulint
46
 
rec_get_next_offs(
47
 
/*==============*/
48
 
                        /* out: the page offset of the next
49
 
                        chained record */
50
 
        rec_t*  rec,    /* in: physical record */
51
 
        ulint   comp);  /* in: nonzero=compact page format */
52
 
/**********************************************************
53
 
The following function is used to set the next record offset field
54
 
of the record. */
55
 
UNIV_INLINE
56
 
void
57
 
rec_set_next_offs(
58
 
/*==============*/
59
 
        rec_t*  rec,    /* in: physical record */
60
 
        ulint   comp,   /* in: nonzero=compact page format */
61
 
        ulint   next);  /* in: offset of the next record */
62
 
/**********************************************************
63
 
The following function is used to get the number of fields
64
 
in an old-style record. */
65
 
UNIV_INLINE
66
 
ulint
67
 
rec_get_n_fields_old(
68
 
/*=================*/
69
 
                        /* out: number of data fields */
70
 
        rec_t*  rec);   /* in: physical record */
71
 
/**********************************************************
72
 
The following function is used to get the number of fields
73
 
in a record. */
74
 
UNIV_INLINE
75
 
ulint
76
 
rec_get_n_fields(
77
 
/*=============*/
78
 
                                /* out: number of data fields */
79
 
        rec_t*          rec,    /* in: physical record */
80
 
        dict_index_t*   index); /* in: record descriptor */
81
 
/**********************************************************
82
 
The following function is used to get the number of records
83
 
owned by the previous directory record. */
84
 
UNIV_INLINE
85
 
ulint
86
 
rec_get_n_owned(
87
 
/*============*/
88
 
                        /* out: number of owned records */
89
 
        rec_t*  rec,    /* in: physical record */
90
 
        ulint   comp);  /* in: nonzero=compact page format */
91
 
/**********************************************************
92
 
The following function is used to set the number of owned
93
 
records. */
94
 
UNIV_INLINE
95
 
void
96
 
rec_set_n_owned(
97
 
/*============*/
98
 
        rec_t*  rec,            /* in: physical record */
99
 
        ulint   comp,           /* in: nonzero=compact page format */
100
 
        ulint   n_owned);       /* in: the number of owned */
101
 
/**********************************************************
102
 
The following function is used to retrieve the info bits of
103
 
a record. */
104
 
UNIV_INLINE
105
 
ulint
106
 
rec_get_info_bits(
107
 
/*==============*/
108
 
                        /* out: info bits */
109
 
        rec_t*  rec,    /* in: physical record */
110
 
        ulint   comp);  /* in: nonzero=compact page format */
111
 
/**********************************************************
112
 
The following function is used to set the info bits of a record. */
113
 
UNIV_INLINE
114
 
void
115
 
rec_set_info_bits(
116
 
/*==============*/
117
 
        rec_t*  rec,    /* in: physical record */
118
 
        ulint   comp,   /* in: nonzero=compact page format */
119
 
        ulint   bits);  /* in: info bits */
120
 
/**********************************************************
121
 
The following function retrieves the status bits of a new-style record. */
122
 
UNIV_INLINE
123
 
ulint
124
 
rec_get_status(
125
 
/*===========*/
126
 
                        /* out: status bits */
127
 
        rec_t*  rec);   /* in: physical record */
128
 
 
129
 
/**********************************************************
130
 
The following function is used to set the status bits of a new-style record. */
131
 
UNIV_INLINE
132
 
void
133
 
rec_set_status(
134
 
/*===========*/
135
 
        rec_t*  rec,    /* in: physical record */
136
 
        ulint   bits);  /* in: info bits */
137
 
 
138
 
/**********************************************************
139
 
The following function is used to retrieve the info and status
140
 
bits of a record.  (Only compact records have status bits.) */
141
 
UNIV_INLINE
142
 
ulint
143
 
rec_get_info_and_status_bits(
144
 
/*=========================*/
145
 
                        /* out: info bits */
146
 
        rec_t*  rec,    /* in: physical record */
147
 
        ulint   comp);  /* in: nonzero=compact page format */
148
 
/**********************************************************
149
 
The following function is used to set the info and status
150
 
bits of a record.  (Only compact records have status bits.) */
151
 
UNIV_INLINE
152
 
void
153
 
rec_set_info_and_status_bits(
154
 
/*=========================*/
155
 
        rec_t*  rec,    /* in: physical record */
156
 
        ulint   comp,   /* in: nonzero=compact page format */
157
 
        ulint   bits);  /* in: info bits */
158
 
 
159
 
/**********************************************************
160
 
The following function tells if record is delete marked. */
161
 
UNIV_INLINE
162
 
ulint
163
 
rec_get_deleted_flag(
164
 
/*=================*/
165
 
                        /* out: nonzero if delete marked */
166
 
        rec_t*  rec,    /* in: physical record */
167
 
        ulint   comp);  /* in: nonzero=compact page format */
168
 
/**********************************************************
169
 
The following function is used to set the deleted bit. */
170
 
UNIV_INLINE
171
 
void
172
 
rec_set_deleted_flag(
173
 
/*=================*/
174
 
        rec_t*  rec,    /* in: physical record */
175
 
        ulint   comp,   /* in: nonzero=compact page format */
176
 
        ulint   flag);  /* in: nonzero if delete marked */
177
 
/**********************************************************
178
 
The following function tells if a new-style record is a node pointer. */
179
 
UNIV_INLINE
180
 
ibool
181
 
rec_get_node_ptr_flag(
182
 
/*==================*/
183
 
                        /* out: TRUE if node pointer */
184
 
        rec_t*  rec);   /* in: physical record */
185
 
/**********************************************************
186
 
The following function is used to get the order number
187
 
of the record in the heap of the index page. */
188
 
UNIV_INLINE
189
 
ulint
190
 
rec_get_heap_no(
191
 
/*============*/
192
 
                        /* out: heap order number */
193
 
        rec_t*  rec,    /* in: physical record */
194
 
        ulint   comp);  /* in: nonzero=compact page format */
195
 
/**********************************************************
196
 
The following function is used to set the heap number
197
 
field in the record. */
198
 
UNIV_INLINE
199
 
void
200
 
rec_set_heap_no(
201
 
/*============*/
202
 
        rec_t*  rec,    /* in: physical record */
203
 
        ulint   comp,   /* in: nonzero=compact page format */
204
 
        ulint   heap_no);/* in: the heap number */
205
 
/**********************************************************
206
 
The following function is used to test whether the data offsets
207
 
in the record are stored in one-byte or two-byte format. */
208
 
UNIV_INLINE
209
 
ibool
210
 
rec_get_1byte_offs_flag(
211
 
/*====================*/
212
 
                        /* out: TRUE if 1-byte form */
213
 
        rec_t*  rec);   /* in: physical record */
214
 
/**********************************************************
215
 
The following function determines the offsets to each field
216
 
in the record.  It can reuse a previously allocated array. */
217
 
 
218
 
ulint*
219
 
rec_get_offsets_func(
220
 
/*=================*/
221
 
                                /* out: the new offsets */
222
 
        rec_t*          rec,    /* in: physical record */
223
 
        dict_index_t*   index,  /* in: record descriptor */
224
 
        ulint*          offsets,/* in: array consisting of offsets[0]
225
 
                                allocated elements, or an array from
226
 
                                rec_get_offsets(), or NULL */
227
 
        ulint           n_fields,/* in: maximum number of initialized fields
228
 
                                (ULINT_UNDEFINED if all fields) */
229
 
        mem_heap_t**    heap,   /* in/out: memory heap */
230
 
        const char*     file,   /* in: file name where called */
231
 
        ulint           line);  /* in: line number where called */
232
 
 
233
 
#define rec_get_offsets(rec,index,offsets,n,heap)       \
234
 
        rec_get_offsets_func(rec,index,offsets,n,heap,__FILE__,__LINE__)
235
 
 
236
 
/****************************************************************
237
 
Validates offsets returned by rec_get_offsets(). */
238
 
UNIV_INLINE
239
 
ibool
240
 
rec_offs_validate(
241
 
/*==============*/
242
 
                                /* out: TRUE if valid */
243
 
        rec_t*          rec,    /* in: record or NULL */
244
 
        dict_index_t*   index,  /* in: record descriptor or NULL */
245
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
246
 
/****************************************************************
247
 
Updates debug data in offsets, in order to avoid bogus
248
 
rec_offs_validate() failures. */
249
 
UNIV_INLINE
250
 
void
251
 
rec_offs_make_valid(
252
 
/*================*/
253
 
        rec_t*          rec,    /* in: record */
254
 
        dict_index_t*   index,/* in: record descriptor */
255
 
        const ulint*            offsets);/* in: array returned by rec_get_offsets() */
256
 
 
257
 
/****************************************************************
258
 
The following function is used to get a pointer to the nth
259
 
data field in an old-style record. */
260
 
 
261
 
byte*
262
 
rec_get_nth_field_old(
263
 
/*==================*/
264
 
                        /* out: pointer to the field */
265
 
        rec_t*  rec,    /* in: record */
266
 
        ulint   n,      /* in: index of the field */
267
 
        ulint*  len);   /* out: length of the field; UNIV_SQL_NULL
268
 
                        if SQL null */
269
 
/****************************************************************
270
 
Gets the physical size of an old-style field.
271
 
Also an SQL null may have a field of size > 0,
272
 
if the data type is of a fixed size. */
273
 
UNIV_INLINE
274
 
ulint
275
 
rec_get_nth_field_size(
276
 
/*===================*/
277
 
                        /* out: field size in bytes */
278
 
        rec_t*  rec,    /* in: record */
279
 
        ulint   n);     /* in: index of the field */
280
 
/****************************************************************
281
 
The following function is used to get a pointer to the nth
282
 
data field in a record. */
283
 
UNIV_INLINE
284
 
byte*
285
 
rec_get_nth_field(
286
 
/*==============*/
287
 
                                /* out: pointer to the field */
288
 
        rec_t*          rec,    /* in: record */
289
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
290
 
        ulint           n,      /* in: index of the field */
291
 
        ulint*          len);   /* out: length of the field; UNIV_SQL_NULL
292
 
                                if SQL null */
293
 
/**********************************************************
294
 
Determine if the offsets are for a record in the new
295
 
compact format. */
296
 
UNIV_INLINE
297
 
ulint
298
 
rec_offs_comp(
299
 
/*==========*/
300
 
                                /* out: nonzero if compact format */
301
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
302
 
/**********************************************************
303
 
Returns nonzero if the extern bit is set in nth field of rec. */
304
 
UNIV_INLINE
305
 
ulint
306
 
rec_offs_nth_extern(
307
 
/*================*/
308
 
                                /* out: nonzero if externally stored */
309
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
310
 
        ulint           n);     /* in: nth field */
311
 
/**********************************************************
312
 
Returns nonzero if the SQL NULL bit is set in nth field of rec. */
313
 
UNIV_INLINE
314
 
ulint
315
 
rec_offs_nth_sql_null(
316
 
/*==================*/
317
 
                                /* out: nonzero if SQL NULL */
318
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
319
 
        ulint           n);     /* in: nth field */
320
 
/**********************************************************
321
 
Gets the physical size of a field. */
322
 
UNIV_INLINE
323
 
ulint
324
 
rec_offs_nth_size(
325
 
/*==============*/
326
 
                                /* out: length of field */
327
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
328
 
        ulint           n);     /* in: nth field */
329
 
 
330
 
/**********************************************************
331
 
Returns TRUE if the extern bit is set in any of the fields
332
 
of rec. */
333
 
UNIV_INLINE
334
 
ibool
335
 
rec_offs_any_extern(
336
 
/*================*/
337
 
                                /* out: TRUE if a field is stored externally */
338
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
339
 
/***************************************************************
340
 
Sets the value of the ith field extern storage bit. */
341
 
UNIV_INLINE
342
 
void
343
 
rec_set_nth_field_extern_bit(
344
 
/*=========================*/
345
 
        rec_t*          rec,    /* in: record */
346
 
        dict_index_t*   index,  /* in: record descriptor */
347
 
        ulint           i,      /* in: ith field */
348
 
        ibool           val,    /* in: value to set */
349
 
        mtr_t*          mtr);   /* in: mtr holding an X-latch to the page
350
 
                                where rec is, or NULL; in the NULL case
351
 
                                we do not write to log about the change */
352
 
/***************************************************************
353
 
Sets TRUE the extern storage bits of fields mentioned in an array. */
354
 
 
355
 
void
356
 
rec_set_field_extern_bits(
357
 
/*======================*/
358
 
        rec_t*          rec,    /* in: record */
359
 
        dict_index_t*   index,  /* in: record descriptor */
360
 
        const ulint*    vec,    /* in: array of field numbers */
361
 
        ulint           n_fields,/* in: number of fields numbers */
362
 
        mtr_t*          mtr);   /* in: mtr holding an X-latch to the page
363
 
                                where rec is, or NULL; in the NULL case
364
 
                                we do not write to log about the change */
365
 
/***************************************************************
366
 
This is used to modify the value of an already existing field in a record.
367
 
The previous value must have exactly the same size as the new value. If len
368
 
is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
369
 
records. For new-style records, len must not be UNIV_SQL_NULL. */
370
 
UNIV_INLINE
371
 
void
372
 
rec_set_nth_field(
373
 
/*==============*/
374
 
        rec_t*          rec,    /* in: record */
375
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
376
 
        ulint           n,      /* in: index number of the field */
377
 
        const void*     data,   /* in: pointer to the data if not SQL null */
378
 
        ulint           len);   /* in: length of the data or UNIV_SQL_NULL.
379
 
                                If not SQL null, must have the same
380
 
                                length as the previous value.
381
 
                                If SQL null, previous value must be
382
 
                                SQL null. */
383
 
/**************************************************************
384
 
The following function returns the data size of an old-style physical
385
 
record, that is the sum of field lengths. SQL null fields
386
 
are counted as length 0 fields. The value returned by the function
387
 
is the distance from record origin to record end in bytes. */
388
 
UNIV_INLINE
389
 
ulint
390
 
rec_get_data_size_old(
391
 
/*==================*/
392
 
                                /* out: size */
393
 
        rec_t*  rec);   /* in: physical record */
394
 
/**************************************************************
395
 
The following function returns the number of fields in a record. */
396
 
UNIV_INLINE
397
 
ulint
398
 
rec_offs_n_fields(
399
 
/*==============*/
400
 
                                /* out: number of fields */
401
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
402
 
/**************************************************************
403
 
The following function returns the data size of a physical
404
 
record, that is the sum of field lengths. SQL null fields
405
 
are counted as length 0 fields. The value returned by the function
406
 
is the distance from record origin to record end in bytes. */
407
 
UNIV_INLINE
408
 
ulint
409
 
rec_offs_data_size(
410
 
/*===============*/
411
 
                                /* out: size */
412
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
413
 
/**************************************************************
414
 
Returns the total size of record minus data size of record.
415
 
The value returned by the function is the distance from record
416
 
start to record origin in bytes. */
417
 
UNIV_INLINE
418
 
ulint
419
 
rec_offs_extra_size(
420
 
/*================*/
421
 
                                /* out: size */
422
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
423
 
/**************************************************************
424
 
Returns the total size of a physical record.  */
425
 
UNIV_INLINE
426
 
ulint
427
 
rec_offs_size(
428
 
/*==========*/
429
 
                                /* out: size */
430
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
431
 
/**************************************************************
432
 
Returns a pointer to the start of the record. */
433
 
UNIV_INLINE
434
 
byte*
435
 
rec_get_start(
436
 
/*==========*/
437
 
                                /* out: pointer to start */
438
 
        rec_t*          rec,    /* in: pointer to record */
439
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
440
 
/**************************************************************
441
 
Returns a pointer to the end of the record. */
442
 
UNIV_INLINE
443
 
byte*
444
 
rec_get_end(
445
 
/*========*/
446
 
                                /* out: pointer to end */
447
 
        rec_t*          rec,    /* in: pointer to record */
448
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
449
 
/*******************************************************************
450
 
Copies a physical record to a buffer. */
451
 
UNIV_INLINE
452
 
rec_t*
453
 
rec_copy(
454
 
/*=====*/
455
 
                                /* out: pointer to the origin of the copy */
456
 
        void*           buf,    /* in: buffer */
457
 
        const rec_t*    rec,    /* in: physical record */
458
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
459
 
/******************************************************************
460
 
Copies the first n fields of a physical record to a new physical record in
461
 
a buffer. */
462
 
 
463
 
rec_t*
464
 
rec_copy_prefix_to_buf(
465
 
/*===================*/
466
 
                                        /* out, own: copied record */
467
 
        rec_t*          rec,            /* in: physical record */
468
 
        dict_index_t*   index,          /* in: record descriptor */
469
 
        ulint           n_fields,       /* in: number of fields to copy */
470
 
        byte**          buf,            /* in/out: memory buffer
471
 
                                        for the copied prefix, or NULL */
472
 
        ulint*          buf_size);      /* in/out: buffer size */
473
 
/****************************************************************
474
 
Folds a prefix of a physical record to a ulint. */
475
 
UNIV_INLINE
476
 
ulint
477
 
rec_fold(
478
 
/*=====*/
479
 
                                        /* out: the folded value */
480
 
        rec_t*          rec,            /* in: the physical record */
481
 
        const ulint*    offsets,        /* in: array returned by
482
 
                                        rec_get_offsets() */
483
 
        ulint           n_fields,       /* in: number of complete
484
 
                                        fields to fold */
485
 
        ulint           n_bytes,        /* in: number of bytes to fold
486
 
                                        in an incomplete last field */
487
 
        dulint          tree_id);       /* in: index tree id */
488
 
/*************************************************************
489
 
Builds a physical record out of a data tuple and stores it beginning from
490
 
address destination. */
491
 
 
492
 
rec_t*
493
 
rec_convert_dtuple_to_rec(
494
 
/*======================*/
495
 
                                /* out: pointer to the origin
496
 
                                of physical record */
497
 
        byte*           buf,    /* in: start address of the
498
 
                                physical record */
499
 
        dict_index_t*   index,  /* in: record descriptor */
500
 
        dtuple_t*       dtuple);/* in: data tuple */
501
 
/**************************************************************
502
 
Returns the extra size of an old-style physical record if we know its
503
 
data size and number of fields. */
504
 
UNIV_INLINE
505
 
ulint
506
 
rec_get_converted_extra_size(
507
 
/*=========================*/
508
 
                                /* out: extra size */
509
 
        ulint   data_size,      /* in: data size */
510
 
        ulint   n_fields)       /* in: number of fields */
511
 
                __attribute__((const));
512
 
/**************************************************************
513
 
The following function returns the size of a data tuple when converted to
514
 
a physical record. */
515
 
UNIV_INLINE
516
 
ulint
517
 
rec_get_converted_size(
518
 
/*===================*/
519
 
                                /* out: size */
520
 
        dict_index_t*   index,  /* in: record descriptor */
521
 
        dtuple_t*       dtuple);/* in: data tuple */
522
 
/******************************************************************
523
 
Copies the first n fields of a physical record to a data tuple.
524
 
The fields are copied to the memory heap. */
525
 
 
526
 
void
527
 
rec_copy_prefix_to_dtuple(
528
 
/*======================*/
529
 
        dtuple_t*       tuple,          /* in: data tuple */
530
 
        rec_t*          rec,            /* in: physical record */
531
 
        dict_index_t*   index,          /* in: record descriptor */
532
 
        ulint           n_fields,       /* in: number of fields to copy */
533
 
        mem_heap_t*     heap);          /* in: memory heap */
534
 
/*******************************************************************
535
 
Validates the consistency of a physical record. */
536
 
 
537
 
ibool
538
 
rec_validate(
539
 
/*=========*/
540
 
                                /* out: TRUE if ok */
541
 
        rec_t*          rec,    /* in: physical record */
542
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
543
 
/*******************************************************************
544
 
Prints an old-style physical record. */
545
 
 
546
 
void
547
 
rec_print_old(
548
 
/*==========*/
549
 
        FILE*           file,   /* in: file where to print */
550
 
        rec_t*          rec);   /* in: physical record */
551
 
/*******************************************************************
552
 
Prints a physical record. */
553
 
 
554
 
void
555
 
rec_print_new(
556
 
/*==========*/
557
 
        FILE*           file,   /* in: file where to print */
558
 
        rec_t*          rec,    /* in: physical record */
559
 
        const ulint*    offsets);/* in: array returned by rec_get_offsets() */
560
 
/*******************************************************************
561
 
Prints a physical record. */
562
 
 
563
 
void
564
 
rec_print(
565
 
/*======*/
566
 
        FILE*           file,   /* in: file where to print */
567
 
        rec_t*          rec,    /* in: physical record */
568
 
        dict_index_t*   index); /* in: record descriptor */
569
 
 
570
 
#define REC_INFO_BITS           6       /* This is single byte bit-field */
571
 
 
572
 
/* Maximum lengths for the data in a physical record if the offsets
573
 
are given in one byte (resp. two byte) format. */
574
 
#define REC_1BYTE_OFFS_LIMIT    0x7FUL
575
 
#define REC_2BYTE_OFFS_LIMIT    0x7FFFUL
576
 
 
577
 
/* The data size of record must be smaller than this because we reserve
578
 
two upmost bits in a two byte offset for special purposes */
579
 
#define REC_MAX_DATA_SIZE       (16 * 1024)
580
 
 
581
 
#ifndef UNIV_NONINL
582
 
#include "rem0rec.ic"
583
 
#endif
584
 
 
585
 
#endif