~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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
        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