1 : /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult 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
14 : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15 :
16 : /*
17 : Read and write key blocks
18 :
19 : The basic structure of a key block is as follows:
20 :
21 : LSN 7 (LSN_STORE_SIZE); Log number for last change;
22 : Only for transactional pages
23 : PACK_TRANSID 6 (TRANSID_SIZE); Relative transid to pack page transid's
24 : Only for transactional pages
25 : KEYNR 1 (KEYPAGE_KEYID_SIZE) Which index this page belongs to
26 : FLAG 1 (KEYPAGE_FLAG_SIZE) Flags for page
27 : PAGE_SIZE 2 (KEYPAGE_USED_SIZE) How much of the page is used.
28 : high-byte-first
29 :
30 : The flag is a combination of the following values:
31 :
32 : KEYPAGE_FLAG_ISNOD Page is a node
33 : KEYPAGE_FLAG_HAS_TRANSID There may be a transid on the page.
34 :
35 : After this we store key data, either packed or not packed, directly
36 : after each other. If the page is a node flag, there is a pointer to
37 : the next key page at page start and after each key.
38 :
39 : At end of page the last KEYPAGE_CHECKSUM_SIZE bytes are reserved for a
40 : page checksum.
41 : */
42 :
43 : #include "maria_def.h"
44 : #include "trnman.h"
45 : #include "ma_key_recover.h"
46 :
47 : /**
48 : Fill MARIA_PAGE structure for usage with _ma_write_keypage
49 : */
50 :
51 : void _ma_page_setup(MARIA_PAGE *page, MARIA_HA *info,
52 : const MARIA_KEYDEF *keyinfo, my_off_t pos,
53 : uchar *buff)
54 957183 : {
55 957183 : MARIA_SHARE *share= info->s;
56 :
57 957183 : page->info= info;
58 957183 : page->keyinfo= keyinfo;
59 957183 : page->buff= buff;
60 957183 : page->pos= pos;
61 957183 : page->size= _ma_get_page_used(share, buff);
62 957183 : page->flag= _ma_get_keypage_flag(share, buff);
63 957183 : page->node= ((page->flag & KEYPAGE_FLAG_ISNOD) ?
64 : share->base.key_reflength : 0);
65 : }
66 :
67 :
68 : /**
69 : Fetch a key-page in memory
70 :
71 : @fn _ma_fetch_keypage()
72 : @param page Fill this struct with information about read page
73 : @param info Maria handler
74 : @param keyinfo Key definition for used key
75 : @param pos Position for page (in bytes)
76 : @param lock Lock type for page
77 : @param level Importance of page; Priority for page cache
78 : @param buff Buffer to use for page
79 : @param return_buffer Set to 1 if we want to force useage of buff
80 :
81 : @return
82 : @retval 0 ok
83 : @retval 1 error
84 : */
85 :
86 : my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info,
87 : const MARIA_KEYDEF *keyinfo,
88 : my_off_t pos, enum pagecache_page_lock lock,
89 : int level, uchar *buff,
90 : my_bool return_buffer __attribute__ ((unused)))
91 4689190 : {
92 : uchar *tmp;
93 : MARIA_PINNED_PAGE page_link;
94 4689190 : MARIA_SHARE *share= info->s;
95 4689190 : uint block_size= share->block_size;
96 4689190 : DBUG_ENTER("_ma_fetch_keypage");
97 4689190 : DBUG_PRINT("enter",("pos: %ld", (long) pos));
98 :
99 4689190 : tmp= pagecache_read(share->pagecache, &share->kfile,
100 : (pgcache_page_no_t) (pos / block_size), level, buff,
101 : share->page_type, lock, &page_link.link);
102 :
103 4689190 : if (lock != PAGECACHE_LOCK_LEFT_UNLOCKED)
104 : {
105 4324999 : DBUG_ASSERT(lock == PAGECACHE_LOCK_WRITE);
106 4324999 : page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
107 4324999 : page_link.changed= 0;
108 4324999 : push_dynamic(&info->pinned_pages, (void*) &page_link);
109 4324999 : page->link_offset= info->pinned_pages.elements-1;
110 : }
111 :
112 4689190 : if (tmp == info->buff)
113 8928 : info->keyread_buff_used=1;
114 4680262 : else if (!tmp)
115 : {
116 0 : DBUG_PRINT("error",("Got errno: %d from pagecache_read",my_errno));
117 0 : info->last_keypage=HA_OFFSET_ERROR;
118 0 : maria_print_error(share, HA_ERR_CRASHED);
119 0 : my_errno=HA_ERR_CRASHED;
120 0 : DBUG_RETURN(1);
121 : }
122 4689190 : info->last_keypage= pos;
123 :
124 : /*
125 : Setup page structure to make pages easy to use
126 : This is same as page_fill_info, but here inlined as this si used
127 : so often.
128 : */
129 4689190 : page->info= info;
130 4689190 : page->keyinfo= keyinfo;
131 4689190 : page->buff= tmp;
132 4689190 : page->pos= pos;
133 4689190 : page->size= _ma_get_page_used(share, tmp);
134 4689190 : page->flag= _ma_get_keypage_flag(share, tmp);
135 4689190 : page->node= ((page->flag & KEYPAGE_FLAG_ISNOD) ?
136 : share->base.key_reflength : 0);
137 :
138 : #ifdef EXTRA_DEBUG
139 : {
140 4689190 : uint page_size= page->size;
141 4689190 : if (page_size < 4 || page_size > block_size ||
142 : _ma_get_keynr(share, tmp) != keyinfo->key_nr)
143 : {
144 0 : DBUG_PRINT("error",("page %lu had wrong page length: %u keynr: %u",
145 : (ulong) (pos / block_size), page_size,
146 : _ma_get_keynr(share, tmp)));
147 0 : DBUG_DUMP("page", tmp, page_size);
148 0 : info->last_keypage = HA_OFFSET_ERROR;
149 0 : maria_print_error(share, HA_ERR_CRASHED);
150 0 : my_errno= HA_ERR_CRASHED;
151 0 : tmp= 0;
152 : }
153 : }
154 : #endif
155 4689190 : DBUG_RETURN(0);
156 : } /* _ma_fetch_keypage */
157 :
158 :
159 : /* Write a key-page on disk */
160 :
161 : my_bool _ma_write_keypage(MARIA_PAGE *page, enum pagecache_page_lock lock,
162 : int level)
163 2583597 : {
164 2583597 : MARIA_SHARE *share= page->info->s;
165 2583597 : uint block_size= share->block_size;
166 2583597 : uchar *buff= page->buff;
167 : my_bool res;
168 : MARIA_PINNED_PAGE page_link;
169 2583597 : DBUG_ENTER("_ma_write_keypage");
170 :
171 : #ifdef EXTRA_DEBUG /* Safety check */
172 : {
173 : uint page_length, nod_flag;
174 2583597 : page_length= _ma_get_page_used(share, buff);
175 2583597 : nod_flag= _ma_test_if_nod(share, buff);
176 :
177 2583597 : DBUG_ASSERT(page->size == page_length);
178 2583597 : DBUG_ASSERT(page->flag == _ma_get_keypage_flag(share, buff));
179 :
180 2583597 : if (page->pos < share->base.keystart ||
181 : page->pos+block_size > share->state.state.key_file_length ||
182 : (page->pos & (maria_block_size-1)))
183 : {
184 0 : DBUG_PRINT("error",("Trying to write inside key status region: "
185 : "key_start: %lu length: %lu page: %lu",
186 : (long) share->base.keystart,
187 : (long) share->state.state.key_file_length,
188 : (long) page->pos));
189 0 : my_errno=EINVAL;
190 0 : DBUG_ASSERT(0);
191 : DBUG_RETURN(1);
192 : }
193 2583597 : DBUG_PRINT("page",("write page at: %lu",(long) page->pos));
194 2583597 : DBUG_DUMP("buff", buff, page_length);
195 2583597 : DBUG_ASSERT(page_length >= share->keypage_header + nod_flag +
196 : page->keyinfo->minlength || maria_in_recovery);
197 : }
198 : #endif
199 :
200 : /* Verify that keynr is correct */
201 2583597 : DBUG_ASSERT(_ma_get_keynr(share, buff) == page->keyinfo->key_nr);
202 :
203 : #if defined(EXTRA_DEBUG) && defined(HAVE_purify) && defined(NOT_ANYMORE)
204 : {
205 : /* This is here to catch uninitialized bytes */
206 : uint length= page->size;
207 : ulong crc= my_checksum(0, buff, length);
208 : int4store(buff + block_size - KEYPAGE_CHECKSUM_SIZE, crc);
209 : }
210 : #endif
211 :
212 : #ifdef IDENTICAL_PAGES_AFTER_RECOVERY
213 : {
214 : uint length= page->size;
215 : DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE);
216 : bzero(buff + length, block_size - length);
217 : }
218 : #endif
219 :
220 2583597 : res= pagecache_write(share->pagecache,
221 : &share->kfile,
222 : (pgcache_page_no_t) (page->pos / block_size),
223 : level, buff, share->page_type,
224 : lock,
225 : lock == PAGECACHE_LOCK_LEFT_WRITELOCKED ?
226 : PAGECACHE_PIN_LEFT_PINNED :
227 : (lock == PAGECACHE_LOCK_WRITE_UNLOCK ?
228 : PAGECACHE_UNPIN : PAGECACHE_PIN),
229 : PAGECACHE_WRITE_DELAY, &page_link.link,
230 : LSN_IMPOSSIBLE);
231 :
232 2583597 : if (lock == PAGECACHE_LOCK_WRITE)
233 : {
234 : /* It was not locked before, we have to unlock it when we unpin pages */
235 4865 : page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
236 4865 : page_link.changed= 1;
237 4865 : push_dynamic(&page->info->pinned_pages, (void*) &page_link);
238 : }
239 2583597 : DBUG_RETURN(res);
240 : }
241 :
242 :
243 : /**
244 : @brief Put page in free list
245 :
246 : @fn _ma_dispose()
247 : @param info Maria handle
248 : @param pos Address to page
249 : @param page_not_read 1 if page has not yet been read
250 :
251 : @note
252 : The page at 'pos' must have been read with a write lock.
253 : This function does logging (unlike _ma_new()).
254 :
255 : @return
256 : @retval 0 ok
257 : @retval 1 error
258 :
259 : */
260 :
261 : int _ma_dispose(register MARIA_HA *info, my_off_t pos, my_bool page_not_read)
262 4071 : {
263 : my_off_t old_link;
264 : uchar buff[MAX_KEYPAGE_HEADER_SIZE+ 8 + 2];
265 : ulonglong page_no;
266 4071 : MARIA_SHARE *share= info->s;
267 : MARIA_PINNED_PAGE page_link;
268 4071 : uint block_size= share->block_size;
269 4071 : int result= 0;
270 : enum pagecache_page_lock lock_method;
271 : enum pagecache_page_pin pin_method;
272 4071 : DBUG_ENTER("_ma_dispose");
273 4071 : DBUG_PRINT("enter",("pos: %ld", (long) pos));
274 4071 : DBUG_ASSERT(pos % block_size == 0);
275 :
276 4071 : (void) _ma_lock_key_del(info, 0);
277 :
278 4071 : old_link= share->key_del_current;
279 4071 : share->key_del_current= pos;
280 4071 : page_no= pos / block_size;
281 4071 : bzero(buff, share->keypage_header);
282 4071 : _ma_store_keynr(share, buff, (uchar) MARIA_DELETE_KEY_NR);
283 4071 : _ma_store_page_used(share, buff, share->keypage_header + 8);
284 4071 : mi_sizestore(buff + share->keypage_header, old_link);
285 4071 : share->state.changed|= STATE_NOT_SORTED_PAGES;
286 :
287 4071 : if (share->now_transactional)
288 : {
289 : LSN lsn;
290 : uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE * 2];
291 : LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
292 : my_off_t page;
293 :
294 : /* Store address of deleted page */
295 2588 : page_store(log_data + FILEID_STORE_SIZE, page_no);
296 :
297 : /* Store link to next unused page (the link that is written to page) */
298 2588 : page= (old_link == HA_OFFSET_ERROR ? IMPOSSIBLE_PAGE_NO :
299 : old_link / block_size);
300 2588 : page_store(log_data + FILEID_STORE_SIZE + PAGE_STORE_SIZE, page);
301 :
302 2588 : log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
303 2588 : log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
304 :
305 2588 : if (translog_write_record(&lsn, LOGREC_REDO_INDEX_FREE_PAGE,
306 : info->trn, info,
307 : (translog_size_t) sizeof(log_data),
308 : TRANSLOG_INTERNAL_PARTS + 1, log_array,
309 : log_data, NULL))
310 0 : result= 1;
311 : }
312 :
313 4071 : if (page_not_read)
314 : {
315 0 : lock_method= PAGECACHE_LOCK_WRITE;
316 0 : pin_method= PAGECACHE_PIN;
317 : }
318 : else
319 : {
320 4071 : lock_method= PAGECACHE_LOCK_LEFT_WRITELOCKED;
321 4071 : pin_method= PAGECACHE_PIN_LEFT_PINNED;
322 : }
323 :
324 4071 : if (pagecache_write_part(share->pagecache,
325 : &share->kfile, (pgcache_page_no_t) page_no,
326 : PAGECACHE_PRIORITY_LOW, buff,
327 : share->page_type,
328 : lock_method, pin_method,
329 : PAGECACHE_WRITE_DELAY, &page_link.link,
330 : LSN_IMPOSSIBLE,
331 : 0, share->keypage_header + 8))
332 0 : result= 1;
333 :
334 : #ifdef IDENTICAL_PAGES_AFTER_RECOVERY
335 : {
336 : uchar *page_buff= pagecache_block_link_to_buffer(page_link.link);
337 : bzero(page_buff + share->keypage_header + 8,
338 : block_size - share->keypage_header - 8 - KEYPAGE_CHECKSUM_SIZE);
339 : }
340 : #endif
341 :
342 4071 : if (page_not_read)
343 : {
344 : /* It was not locked before, we have to unlock it when we unpin pages */
345 0 : page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
346 0 : page_link.changed= 1;
347 0 : push_dynamic(&info->pinned_pages, (void*) &page_link);
348 : }
349 :
350 4071 : DBUG_RETURN(result);
351 : } /* _ma_dispose */
352 :
353 :
354 : /**
355 : @brief Get address for free page to use
356 :
357 : @fn _ma_new()
358 : @param info Maria handle
359 : @param level Type of key block (caching priority for pagecache)
360 : @param page_link Pointer to page in page cache if read. One can
361 : check if this is used by checking if
362 : page_link->changed != 0
363 :
364 : @note Logging of this is left to the caller (so that the "new"ing and the
365 : first changes done to this new page can be logged as one single entry - one
366 : single _ma_log_new()) call).
367 :
368 : @return
369 : HA_OFFSET_ERROR File is full or page read error
370 : # Page address to use
371 : */
372 :
373 : my_off_t _ma_new(register MARIA_HA *info, int level,
374 : MARIA_PINNED_PAGE **page_link)
375 :
376 5370 : {
377 : my_off_t pos;
378 5370 : MARIA_SHARE *share= info->s;
379 5370 : uint block_size= share->block_size;
380 5370 : DBUG_ENTER("_ma_new");
381 :
382 5370 : if (_ma_lock_key_del(info, 1))
383 : {
384 4964 : pthread_mutex_lock(&share->intern_lock);
385 4964 : pos= share->state.state.key_file_length;
386 4964 : if (pos >= share->base.max_key_file_length - block_size)
387 : {
388 0 : my_errno=HA_ERR_INDEX_FILE_FULL;
389 0 : pthread_mutex_unlock(&share->intern_lock);
390 0 : DBUG_RETURN(HA_OFFSET_ERROR);
391 : }
392 4964 : share->state.state.key_file_length+= block_size;
393 : /* Following is for not transactional tables */
394 4964 : info->state->key_file_length= share->state.state.key_file_length;
395 4964 : pthread_mutex_unlock(&share->intern_lock);
396 4964 : (*page_link)->changed= 0;
397 4964 : (*page_link)->write_lock= PAGECACHE_LOCK_WRITE;
398 : }
399 : else
400 : {
401 : uchar *buff;
402 406 : pos= share->key_del_current; /* Protected */
403 406 : DBUG_ASSERT(share->pagecache->block_size == block_size);
404 406 : if (!(buff= pagecache_read(share->pagecache,
405 : &share->kfile,
406 : (pgcache_page_no_t) (pos / block_size), level,
407 : 0, share->page_type,
408 : PAGECACHE_LOCK_WRITE, &(*page_link)->link)))
409 0 : pos= HA_OFFSET_ERROR;
410 : else
411 : {
412 : /*
413 : Next deleted page's number is in the header of the present page
414 : (single linked list):
415 : */
416 : #ifndef DBUG_OFF
417 : my_off_t key_del_current;
418 : #endif
419 406 : share->key_del_current= mi_sizekorr(buff+share->keypage_header);
420 : #ifndef DBUG_OFF
421 406 : key_del_current= share->key_del_current;
422 406 : DBUG_ASSERT(key_del_current != share->state.key_del &&
423 : (key_del_current != 0) &&
424 : ((key_del_current == HA_OFFSET_ERROR) ||
425 : (key_del_current <=
426 : (share->state.state.key_file_length - block_size))));
427 : #endif
428 : }
429 :
430 406 : (*page_link)->unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
431 406 : (*page_link)->write_lock= PAGECACHE_LOCK_WRITE;
432 : /*
433 : We have to mark it changed as _ma_flush_pending_blocks() uses
434 : 'changed' to know if we used the page cache or not
435 : */
436 406 : (*page_link)->changed= 1;
437 406 : push_dynamic(&info->pinned_pages, (void*) *page_link);
438 406 : *page_link= dynamic_element(&info->pinned_pages,
439 : info->pinned_pages.elements-1,
440 : MARIA_PINNED_PAGE *);
441 : }
442 5370 : share->state.changed|= STATE_NOT_SORTED_PAGES;
443 5370 : DBUG_PRINT("exit",("Pos: %ld",(long) pos));
444 5370 : DBUG_RETURN(pos);
445 : } /* _ma_new */
446 :
447 :
448 : /**
449 : Log compactation of a index page
450 : */
451 :
452 : static my_bool _ma_log_compact_keypage(MARIA_HA *info, my_off_t page,
453 : TrID min_read_from)
454 0 : {
455 : LSN lsn;
456 : uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 1 + TRANSID_SIZE];
457 : LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
458 0 : MARIA_SHARE *share= info->s;
459 0 : DBUG_ENTER("_ma_log_compact_keypage");
460 0 : DBUG_PRINT("enter", ("page: %lu", (ulong) page));
461 :
462 : /* Store address of new root page */
463 0 : page/= share->block_size;
464 0 : page_store(log_data + FILEID_STORE_SIZE, page);
465 :
466 0 : log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE]= KEY_OP_COMPACT_PAGE;
467 0 : transid_store(log_data + FILEID_STORE_SIZE + PAGE_STORE_SIZE +1,
468 : min_read_from);
469 :
470 0 : log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
471 0 : log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
472 :
473 0 : if (translog_write_record(&lsn, LOGREC_REDO_INDEX,
474 : info->trn, info,
475 : (translog_size_t) sizeof(log_data),
476 : TRANSLOG_INTERNAL_PARTS + 1, log_array,
477 : log_data, NULL))
478 0 : DBUG_RETURN(1);
479 0 : DBUG_RETURN(0);
480 : }
481 :
482 :
483 : /**
484 : Remove all transaction id's less than given one from a key page
485 :
486 : @fn _ma_compact_keypage()
487 : @param keyinfo Key handler
488 : @param page_pos Page position on disk
489 : @param page Buffer for page
490 : @param min_read_from Remove all trids from page less than this
491 :
492 : @retval 0 Ok
493 : Ūretval 1 Error; my_errno contains the error
494 : */
495 :
496 : my_bool _ma_compact_keypage(MARIA_PAGE *ma_page, TrID min_read_from)
497 244 : {
498 244 : MARIA_HA *info= ma_page->info;
499 244 : MARIA_SHARE *share= info->s;
500 : MARIA_KEY key;
501 : uchar *page, *endpos, *start_of_empty_space;
502 : uint page_flag, nod_flag, saved_space;
503 : my_bool page_has_transid;
504 244 : DBUG_ENTER("_ma_compact_keypage");
505 :
506 244 : page_flag= ma_page->flag;
507 244 : if (!(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
508 136 : DBUG_RETURN(0); /* No transaction id on page */
509 :
510 108 : nod_flag= ma_page->node;
511 108 : page= ma_page->buff;
512 108 : endpos= page + ma_page->size;
513 108 : key.data= info->lastkey_buff;
514 108 : key.keyinfo= (MARIA_KEYDEF*) ma_page->keyinfo;
515 :
516 108 : page_has_transid= 0;
517 108 : page+= share->keypage_header + nod_flag;
518 108 : key.data[0]= 0; /* safety */
519 108 : start_of_empty_space= 0;
520 108 : saved_space= 0;
521 : do
522 : {
523 10620 : if (!(page= (*ma_page->keyinfo->skip_key)(&key, 0, 0, page)))
524 : {
525 0 : DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
526 : (long) page));
527 0 : maria_print_error(share, HA_ERR_CRASHED);
528 0 : my_errno=HA_ERR_CRASHED;
529 0 : DBUG_RETURN(1);
530 : }
531 10620 : if (key_has_transid(page-1))
532 : {
533 : uint transid_length;
534 10620 : transid_length= transid_packed_length(page);
535 :
536 21240 : if (min_read_from == ~(TrID) 0 ||
537 : min_read_from < transid_get_packed(share, page))
538 : {
539 10620 : page[-1]&= 254; /* Remove transid marker */
540 10620 : transid_length= transid_packed_length(page);
541 10620 : if (start_of_empty_space)
542 : {
543 : /* Move block before the transid up in page */
544 10512 : uint copy_length= (uint) (page - start_of_empty_space) - saved_space;
545 10512 : memmove(start_of_empty_space, start_of_empty_space + saved_space,
546 : copy_length);
547 10512 : start_of_empty_space+= copy_length;
548 : }
549 : else
550 108 : start_of_empty_space= page;
551 10620 : saved_space+= transid_length;
552 : }
553 : else
554 0 : page_has_transid= 1; /* At least one id left */
555 10620 : page+= transid_length;
556 : }
557 10620 : page+= nod_flag;
558 10620 : } while (page < endpos);
559 :
560 108 : DBUG_ASSERT(page == endpos);
561 :
562 108 : if (start_of_empty_space)
563 : {
564 : /*
565 : Move last block down
566 : This is always true if any transid was removed
567 : */
568 108 : uint copy_length= (uint) (endpos - start_of_empty_space) - saved_space;
569 :
570 108 : if (copy_length)
571 8 : memmove(start_of_empty_space, start_of_empty_space + saved_space,
572 : copy_length);
573 108 : ma_page->size= (uint) (start_of_empty_space + copy_length - ma_page->buff);
574 108 : page_store_size(share, ma_page);
575 : }
576 :
577 108 : if (!page_has_transid)
578 : {
579 108 : ma_page->flag&= ~KEYPAGE_FLAG_HAS_TRANSID;
580 108 : _ma_store_keypage_flag(share, ma_page->buff, ma_page->flag);
581 : /* Clear packed transid (in case of zerofill) */
582 108 : bzero(ma_page->buff + LSN_STORE_SIZE, TRANSID_SIZE);
583 : }
584 :
585 108 : if (share->now_transactional)
586 : {
587 0 : if (_ma_log_compact_keypage(info, ma_page->pos, min_read_from))
588 0 : DBUG_RETURN(1);
589 : }
590 108 : DBUG_RETURN(0);
591 : }
|