CUBRID Engine  latest
overflow_file.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * overflow_file.c - Overflow file manager (at server)
21  */
22 
23 #ident "$Id$"
24 
25 #include "overflow_file.h"
26 
27 #include "config.h"
28 #include "error_manager.h"
29 #include "file_manager.h"
30 #include "heap_file.h"
31 #include "log_append.hpp"
32 #include "log_manager.h"
33 #include "memory_alloc.h"
34 #include "mvcc.h"
35 #include "page_buffer.h"
36 #include "slotted_page.h"
37 #include "storage_common.h"
38 
39 #include <string.h>
40 
41 #define OVERFLOW_ALLOCVPID_ARRAY_SIZE 64
42 
45 {
47  int length;
48  char data[1]; /* Really more than one */
49 };
50 
53 {
55  char data[1]; /* Really more than one */
56 };
57 
58 typedef enum
59 {
63 
64 static void overflow_next_vpid (const VPID * ovf_vpid, VPID * vpid, PAGE_PTR pgptr);
65 static const VPID *overflow_traverse (THREAD_ENTRY * thread_p, const VFID * ovf_vfid, const VPID * ovf_vpid,
66  OVERFLOW_DO_FUNC func);
67 static int overflow_delete_internal (THREAD_ENTRY * thread_p, const VFID * ovf_vfid, VPID * vpid, PAGE_PTR pgptr);
68 static int overflow_flush_internal (THREAD_ENTRY * thread_p, PAGE_PTR pgptr);
69 
70 /*
71  * overflow_insert () - Insert an overflow record (multiple-pages size record).
72  *
73  * return : Error code
74  * thread_p (in) : Thread entry
75  * ovf_vfid (in) : Overflow file identifier
76  * ovf_vpid (out) : Output VPID of first page in multi-page data
77  * recdes (in) : Multi-page data
78  * file_type (in) : Overflow file type
79  *
80  * Note: Data in overflow is composed of several pages. Pages in the overflow
81  * area are not shared among other pieces of overflow data.
82  *
83  * -------------------------------- ------------------------
84  * |Next_vpid |Length|... data ...| ... --> |Next_vpid|... data ...|
85  * -------------------------------- ------------------------
86  *
87  * Single link list of pages.
88  * The length of the multi-page data is stored on its first overflow page
89  *
90  * Overflow pages are not locked in any mode since they are not shared
91  * by other pieces of data and its address is only know by accessing the
92  * relocation overflow record data which has been appropriately locked.
93  */
94 int
95 overflow_insert (THREAD_ENTRY * thread_p, const VFID * ovf_vfid, VPID * ovf_vpid, RECDES * recdes, FILE_TYPE file_type)
96 {
97  OVERFLOW_FIRST_PART *first_part;
98  OVERFLOW_REST_PART *rest_parts;
99  char *copyto;
100  int length, copy_length;
101  INT32 npages = 0;
102  char *data;
103  LOG_DATA_ADDR addr;
104  int i;
105  VPID *vpids = NULL;
106  VPID vpids_buffer[OVERFLOW_ALLOCVPID_ARRAY_SIZE + 1];
107  bool is_sysop_started = false;
108  PAGE_TYPE ptype = PAGE_OVERFLOW;
109 
110  int error_code = NO_ERROR;
111 
112  assert (ovf_vfid != NULL && !VFID_ISNULL (ovf_vfid));
113  assert (ovf_vpid != NULL);
114  assert (recdes != NULL);
115  assert (file_type == FILE_TEMP /* sort files */
116  || file_type == FILE_BTREE_OVERFLOW_KEY /* b-tree overflow key */
117  || file_type == FILE_MULTIPAGE_OBJECT_HEAP /* heap overflow file */ );
118 
119  addr.vfid = ovf_vfid;
120  addr.offset = 0;
121 
122  /*
123  * Guess the number of pages. The total number of pages is found by dividing length by page size - the smallest
124  * header. Then, we make sure that this estimate is correct. */
125  length = recdes->length - (DB_PAGESIZE - (int) offsetof (OVERFLOW_FIRST_PART, data));
126  if (length > 0)
127  {
128  i = DB_PAGESIZE - offsetof (OVERFLOW_REST_PART, data);
129  npages = 1 + CEIL_PTVDIV (length, i);
130  }
131  else
132  {
133  npages = 1;
134  }
135 
136  if (npages > OVERFLOW_ALLOCVPID_ARRAY_SIZE)
137  {
138  vpids = (VPID *) malloc ((npages + 1) * sizeof (VPID));
139  if (vpids == NULL)
140  {
141  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (npages + 1) * sizeof (VPID));
143  }
144  }
145  else
146  {
147  vpids = vpids_buffer;
148  }
149 
150 #if !defined(NDEBUG)
151  for (i = 0; i < npages; i++)
152  {
153  VPID_SET_NULL (&vpids[i]);
154  }
155 #endif
156 
157  VPID_SET_NULL (&vpids[npages]);
158 
159  log_sysop_start (thread_p);
160  is_sysop_started = true;
161 
162  error_code = file_alloc_multiple (thread_p, ovf_vfid,
163  file_type != FILE_TEMP ? file_init_page_type : file_init_temp_page_type, &ptype,
164  npages, vpids);
165  if (error_code != NO_ERROR)
166  {
167  ASSERT_ERROR ();
168  goto exit_on_error;
169  }
170 #if !defined(NDEBUG)
171  for (i = 0; i < npages; i++)
172  {
173  assert (!VPID_ISNULL (&vpids[i]));
174  }
175 #endif
176 
177  *ovf_vpid = vpids[0];
178 
179  /* Copy the content of the data */
180 
181  data = recdes->data;
182  length = recdes->length;
183 
184  for (i = 0; i < npages; i++)
185  {
186  addr.pgptr = pgbuf_fix (thread_p, &vpids[i], OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
187  if (addr.pgptr == NULL)
188  {
189  ASSERT_ERROR_AND_SET (error_code);
190  goto exit_on_error;
191  }
192  (void) pgbuf_check_page_ptype (thread_p, addr.pgptr, PAGE_OVERFLOW);
193 
194  /* Is this the first page ? */
195  if (i == 0)
196  {
197  /* This is the first part */
198  first_part = (OVERFLOW_FIRST_PART *) addr.pgptr;
199 
200  first_part->next_vpid = vpids[i + 1];
201  first_part->length = length;
202  copyto = (char *) first_part->data;
203 
204  copy_length = DB_PAGESIZE - offsetof (OVERFLOW_FIRST_PART, data);
205  if (length < copy_length)
206  {
207  copy_length = length;
208  }
209 
210  /* notify the first part of overflow recdes */
211  if (file_type != FILE_TEMP)
212  {
214  }
215  }
216  else
217  {
218  rest_parts = (OVERFLOW_REST_PART *) addr.pgptr;
219 
220  rest_parts->next_vpid = vpids[i + 1];
221  copyto = (char *) rest_parts->data;
222 
223  copy_length = DB_PAGESIZE - offsetof (OVERFLOW_REST_PART, data);
224  if (length < copy_length)
225  {
226  copy_length = length;
227  }
228  }
229 
230  memcpy (copyto, data, copy_length);
231 
232  if (file_type != FILE_TEMP && thread_p->no_logging != true)
233  {
234  log_append_redo_data (thread_p, RVOVF_NEWPAGE_INSERT, &addr,
235  copy_length + CAST_BUFLEN (copyto - (char *) addr.pgptr), (char *) addr.pgptr);
236  }
237 
238  data += copy_length;
239  length -= copy_length;
240 
241  pgbuf_set_dirty_and_free (thread_p, addr.pgptr);
242  }
243 
244  assert (length == 0);
245 #if defined (CUBRID_DEBUG)
246  if (length > 0)
247  {
248  assert (false);
250  "ovf_insert: ** SYSTEM ERROR calculation of number of pages needed to store overflow data seems"
251  " incorrect. Need no more than %d pages", npages);
252  error_code = ER_FAILED;
253  goto exit_on_error;
254  }
255 #endif
256 
257  log_sysop_attach_to_outer (thread_p);
258 
259  if (vpids != vpids_buffer)
260  {
261  free_and_init (vpids);
262  }
263  return NO_ERROR;
264 
265 exit_on_error:
266 
267  if (is_sysop_started)
268  {
269  log_sysop_abort (thread_p);
270  }
271 
272  if (vpids != vpids_buffer)
273  {
274  free_and_init (vpids);
275  }
276  return error_code;
277 }
278 
279 /*
280  * overflow_next_vpid () -
281  * return: ovf_vpid on success or NULL on failure
282  * ovf_vpid(in): Overflow address
283  * vpid(in/out): current/next vpid
284  * pgptr(in): current page
285  */
286 static void
287 overflow_next_vpid (const VPID * ovf_vpid, VPID * vpid, PAGE_PTR pgptr)
288 {
289  if (VPID_EQ (ovf_vpid, vpid))
290  {
291  *vpid = ((OVERFLOW_FIRST_PART *) pgptr)->next_vpid;
292  }
293  else
294  {
295  *vpid = ((OVERFLOW_REST_PART *) pgptr)->next_vpid;
296  }
297 }
298 
299 /*
300  * overflow_traverse () -
301  * return: ovf_vpid on success or NULL on failure
302  * ovf_vfid(in): File where the overflow data is stored
303  * WARNING: MUST BE THE SAME AS IT WAS GIVEN DURING INSERT
304  * ovf_vpid(in): Overflow address
305  * func(in): Overflow address
306  */
307 static const VPID *
308 overflow_traverse (THREAD_ENTRY * thread_p, const VFID * ovf_vfid, const VPID * ovf_vpid, OVERFLOW_DO_FUNC func)
309 {
310  VPID next_vpid;
311  VPID vpid;
312  PAGE_PTR pgptr = NULL;
313 
314  /*
315  * We don't need to lock the overflow pages since these pages are not
316  * shared among several pieces of overflow data. The overflow pages are
317  * know by accessing the relocation-overflow record with the appropiate lock
318  */
319 
320  next_vpid = *ovf_vpid;
321 
322  while (!(VPID_ISNULL (&next_vpid)))
323  {
324  pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
325  if (pgptr == NULL)
326  {
327  goto exit_on_error;
328  }
329 
330  (void) pgbuf_check_page_ptype (thread_p, pgptr, PAGE_OVERFLOW);
331 
332  vpid = next_vpid;
333  overflow_next_vpid (ovf_vpid, &next_vpid, pgptr);
334 
335  switch (func)
336  {
337  case OVERFLOW_DO_DELETE:
338  if (ovf_vfid == NULL) /* assert */
339  {
340  goto exit_on_error;
341  }
342  if (overflow_delete_internal (thread_p, ovf_vfid, &vpid, pgptr) != NO_ERROR)
343  {
344  goto exit_on_error;
345  }
346  break;
347  case OVERFLOW_DO_FLUSH:
348  if (overflow_flush_internal (thread_p, pgptr) != NO_ERROR)
349  {
350  goto exit_on_error;
351  }
352  break;
353  default:
354  break;
355  }
356  }
357 
358  return ovf_vpid;
359 
360 exit_on_error:
361 
362  /* TODO: suspect pgbuf_unfix */
363  return NULL;
364 }
365 
366 /*
367  * overflow_update () - Update the content of multi-page data.
368  *
369  * return : Error code
370  * thread_p (in) : Thread entry
371  * ovf_vfid (in) : Overflow file identifier
372  * ovf_vpid (in) : VPID of first page in multi-page data
373  * recdes (in) : New multi-page data
374  * file_type (in) : Overflow file type
375  *
376  * Note: The function may allocate or deallocate several overflow pages if the multipage data increase/decrease in
377  * length.
378  *
379  * Overflow pages are not locked in any mode since they are not shared by other data and its address is know by
380  * accessing the relocation overflow record which has been appropriately locked.
381  */
382 int
383 overflow_update (THREAD_ENTRY * thread_p, const VFID * ovf_vfid, const VPID * ovf_vpid, RECDES * recdes,
384  FILE_TYPE file_type)
385 {
386  OVERFLOW_FIRST_PART *first_part = NULL;
387  OVERFLOW_REST_PART *rest_parts = NULL;
388  char *copyto;
389  VPID tmp_vpid;
390  int hdr_length;
391  int copy_length;
392  int old_length = 0;
393  int length;
394  char *data;
395  VPID next_vpid;
396  VPID *addr_vpid_ptr;
397  LOG_DATA_ADDR addr;
398  bool isnewpage = false;
399  PAGE_TYPE ptype = PAGE_OVERFLOW;
400  int error_code = NO_ERROR;
401 
402  assert (ovf_vfid != NULL && !VFID_ISNULL (ovf_vfid));
403 
404  /* used only for heap for now... I left this here just in case other file types start using this.
405  * If you hit this assert, check the code is alright for your usage (e.g. this doesn't consider temporary files).
406  */
407  assert (file_type == FILE_MULTIPAGE_OBJECT_HEAP);
408 
409  addr.vfid = ovf_vfid;
410  addr.offset = 0;
411  next_vpid = *ovf_vpid;
412 
413  data = recdes->data;
414  length = recdes->length;
415 
416  log_sysop_start (thread_p);
417 
418  while (length > 0)
419  {
420  addr.pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
421  if (addr.pgptr == NULL)
422  {
423  ASSERT_ERROR_AND_SET (error_code);
424  goto exit_on_error;
425  }
426  (void) pgbuf_check_page_ptype (thread_p, addr.pgptr, PAGE_OVERFLOW);
427 
428  addr_vpid_ptr = pgbuf_get_vpid_ptr (addr.pgptr);
429 
430  /* Log before and after images */
431 
432  /* Is this the first page ? */
433  if (VPID_EQ (addr_vpid_ptr, ovf_vpid))
434  {
435  /* This is the first part */
436  first_part = (OVERFLOW_FIRST_PART *) addr.pgptr;
437  old_length = first_part->length;
438 
439  copyto = (char *) first_part->data;
440  next_vpid = first_part->next_vpid;
441 
442  hdr_length = offsetof (OVERFLOW_FIRST_PART, data);
443  if ((length + hdr_length) > DB_PAGESIZE)
444  {
445  copy_length = DB_PAGESIZE - hdr_length;
446  }
447  else
448  {
449  copy_length = length;
450  }
451 
452  /* Log before image */
453  if (hdr_length + old_length > DB_PAGESIZE)
454  {
455  log_append_undo_data (thread_p, RVOVF_PAGE_UPDATE, &addr, DB_PAGESIZE, addr.pgptr);
456  old_length -= DB_PAGESIZE - hdr_length;
457  }
458  else
459  {
460  log_append_undo_data (thread_p, RVOVF_PAGE_UPDATE, &addr, hdr_length + old_length, addr.pgptr);
461  old_length = 0;
462  }
463 
464  /* Modify the new length */
465  first_part->length = length;
466 
467  /* notify the first part of overflow recdes */
469  }
470  else
471  {
472  rest_parts = (OVERFLOW_REST_PART *) addr.pgptr;
473  copyto = (char *) rest_parts->data;
474  if (isnewpage == true)
475  {
476  VPID_SET_NULL (&next_vpid);
477  rest_parts->next_vpid = next_vpid;
478  }
479  else
480  {
481  next_vpid = rest_parts->next_vpid;
482  }
483 
484  hdr_length = offsetof (OVERFLOW_REST_PART, data);
485  if ((length + hdr_length) > DB_PAGESIZE)
486  {
487  copy_length = DB_PAGESIZE - hdr_length;
488  }
489  else
490  {
491  copy_length = length;
492  }
493 
494  if (old_length > 0)
495  {
496  if (hdr_length + old_length > DB_PAGESIZE)
497  {
498  log_append_undo_data (thread_p, RVOVF_PAGE_UPDATE, &addr, DB_PAGESIZE, addr.pgptr);
499  old_length -= DB_PAGESIZE - hdr_length;
500  }
501  else
502  {
503  log_append_undo_data (thread_p, RVOVF_PAGE_UPDATE, &addr, hdr_length + old_length, addr.pgptr);
504  old_length = 0;
505  }
506  }
507  }
508 
509  memcpy (copyto, data, copy_length);
510  data += copy_length;
511  length -= copy_length;
512 
513  if (thread_p->no_logging != true)
514  {
515  log_append_redo_data (thread_p, RVOVF_PAGE_UPDATE, &addr, copy_length + hdr_length, (char *) addr.pgptr);
516  }
517 
518  if (length > 0)
519  {
520  /* Need more pages... Get next page */
521  if (VPID_ISNULL (&next_vpid))
522  {
523  /* We need to allocate a new page */
524  error_code = file_alloc (thread_p, ovf_vfid, file_init_page_type, &ptype, &next_vpid, NULL);
525  if (error_code != NO_ERROR)
526  {
527  ASSERT_ERROR ();
528  pgbuf_set_dirty_and_free (thread_p, addr.pgptr);
529 
530  goto exit_on_error;
531  }
532 
533  log_append_undoredo_data (thread_p, RVOVF_NEWPAGE_LINK, &addr, 0, sizeof (next_vpid), NULL, &next_vpid);
534 
535  isnewpage = true; /* So that its link can be set to NULL */
536 
537  if (rest_parts == NULL)
538  {
539  /* This is the first part */
540  first_part->next_vpid = next_vpid;
541  }
542  else
543  {
544  /* This is part of rest part */
545  rest_parts->next_vpid = next_vpid;
546  }
547  }
548  pgbuf_set_dirty_and_free (thread_p, addr.pgptr);
549  }
550  else
551  {
552  /* The content of the data has been copied. We don't need more pages. Deallocate any additional pages */
553  VPID_SET_NULL (&tmp_vpid);
554 
555  log_append_undoredo_data (thread_p, RVOVF_CHANGE_LINK, &addr, sizeof (next_vpid), sizeof (next_vpid),
556  &next_vpid, &tmp_vpid);
557 
558  if (rest_parts == NULL)
559  {
560  /* This is the first part */
561  VPID_SET_NULL (&first_part->next_vpid);
562  }
563  else
564  {
565  /* This is part of rest part */
566  VPID_SET_NULL (&rest_parts->next_vpid);
567  }
568  pgbuf_set_dirty_and_free (thread_p, addr.pgptr);
569 
570  while (!(VPID_ISNULL (&next_vpid)))
571  {
572  addr.pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
573  if (addr.pgptr == NULL)
574  {
575  ASSERT_ERROR_AND_SET (error_code);
576  goto exit_on_error;
577  }
578 
579  (void) pgbuf_check_page_ptype (thread_p, addr.pgptr, PAGE_OVERFLOW);
580 
581  tmp_vpid = next_vpid;
582  rest_parts = (OVERFLOW_REST_PART *) addr.pgptr;
583  next_vpid = rest_parts->next_vpid;
584 
585  pgbuf_unfix_and_init (thread_p, addr.pgptr);
586 
587  error_code = file_dealloc (thread_p, ovf_vfid, &tmp_vpid, file_type);
588  if (error_code != NO_ERROR)
589  {
590  ASSERT_ERROR ();
591  goto exit_on_error;
592  }
593  }
594  break;
595  }
596  }
597 
598  /* done */
599  log_sysop_attach_to_outer (thread_p);
600 
601  return NO_ERROR;
602 
603 exit_on_error:
604 
605  log_sysop_abort (thread_p);
606 
607  return error_code;
608 }
609 
610 /*
611  * overflow_delete_internal () -
612  * return: NO_ERROR
613  * ovf_vfid(in): File where the overflow data is stored
614  * WARNING: MUST BE THE SAME AS IT WAS GIVEN DURING INSERT
615  * vpid(in):
616  * pgptr(in):
617  */
618 static int
619 overflow_delete_internal (THREAD_ENTRY * thread_p, const VFID * ovf_vfid, VPID * vpid, PAGE_PTR pgptr)
620 {
621  int ret;
622 
623  /* Unfix page. */
624  pgbuf_unfix_and_init (thread_p, pgptr);
625 
626  /* TODO: clarify file_type */
627  ret = file_dealloc (thread_p, ovf_vfid, vpid, FILE_UNKNOWN_TYPE);
628  if (ret != NO_ERROR)
629  {
630  goto exit_on_error;
631  }
632 
633  return ret;
634 
635 exit_on_error:
636 
637  return (ret == NO_ERROR && (ret = er_errid ()) == NO_ERROR) ? ER_FAILED : ret;
638 }
639 
640 /*
641  * overflow_delete () - Delete the content of a multipage data
642  * return: ovf_vpid on success or NULL on failure
643  * ovf_vfid(in): File where the overflow data is stored
644  * WARNING: MUST BE THE SAME AS IT WAS GIVEN DURING INSERT
645  * ovf_vpid(in): Overflow address
646  *
647  * Note: The function deallocate the pages composing the overflow record
648  */
649 const VPID *
650 overflow_delete (THREAD_ENTRY * thread_p, const VFID * ovf_vfid, const VPID * ovf_vpid)
651 {
652  return overflow_traverse (thread_p, ovf_vfid, ovf_vpid, OVERFLOW_DO_DELETE);
653 }
654 
655 /*
656  * overflow_flush_internal () -
657  * return: NO_ERROR
658  * pgptr(in):
659  */
660 static int
662 {
663  int ret = NO_ERROR;
664 
665  if (pgbuf_flush_with_wal (thread_p, pgptr) == NULL)
666  {
667  goto exit_on_error;
668  }
669 
670  return ret;
671 
672 exit_on_error:
673 
674  return (ret == NO_ERROR && (ret = er_errid ()) == NO_ERROR) ? ER_FAILED : ret;
675 }
676 
677 /*
678  * overflow_flush () - Flush all overflow dirty pages where the object resides
679  * return: void
680  * ovf_vpid(in): Overflow address
681  */
682 void
683 overflow_flush (THREAD_ENTRY * thread_p, const VPID * ovf_vpid)
684 {
685  (void) overflow_traverse (thread_p, NULL, ovf_vpid, OVERFLOW_DO_FLUSH);
686 }
687 
688 /*
689  * overflow_get_length () - FIND LENGTH OF OVERFLOW OBJECT
690  * return: length of overflow object, or -1 on error
691  * ovf_vpid(in):
692  *
693  * Note: The length of the content of a multipage object associated with the
694  * given overflow address is returned.
695  */
696 int
697 overflow_get_length (THREAD_ENTRY * thread_p, const VPID * ovf_vpid)
698 {
699  PAGE_PTR pgptr;
700  int length;
701 
702  /*
703  * We don't need to lock the overflow pages since these pages are not
704  * shared among several pieces of overflow data. The overflow pages are
705  * know by accessing the relocation-overflow record with the appropiate lock
706  */
707 
708  pgptr = pgbuf_fix (thread_p, ovf_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
709  if (pgptr == NULL)
710  {
711  return -1;
712  }
713 
714  (void) pgbuf_check_page_ptype (thread_p, pgptr, PAGE_OVERFLOW);
715 
716  length = ((OVERFLOW_FIRST_PART *) pgptr)->length;
717 
718  pgbuf_unfix_and_init (thread_p, pgptr);
719 
720  return length;
721 }
722 
723 /*
724  * overflow_get_nbytes () - GET A PORTION OF THE CONTENT OF AN OVERFLOW RECORD
725  * return: scan status
726  * ovf_vpid(in): Overflow address
727  * recdes(in): Record descriptor
728  * start_offset(in): Start offset of portion to copy
729  * max_nbytes(in): Maximum number of bytes to retrieve
730  * remaining_length(in): The number of remaining bytes to read
731  * mvcc_snapshot(in): mvcc snapshot
732  *
733  * Note: A portion of the content of the overflow record associated with the
734  * given overflow address(ovf_pid) is placed into the area pointed to by
735  * the record descriptor. If the content of the object does not fit in
736  * such an area (i.e., recdes->area_size), an error is returned and a
737  * hint of the number of bytes needed is returned as a negative value in
738  * recdes->length. The length of the retrieved number of bytes is *set
739  * in the the record descriptor (i.e., recdes->length).
740  */
741 SCAN_CODE
742 overflow_get_nbytes (THREAD_ENTRY * thread_p, const VPID * ovf_vpid, RECDES * recdes, int start_offset, int max_nbytes,
743  int *remaining_length, MVCC_SNAPSHOT * mvcc_snapshot)
744 {
745  OVERFLOW_FIRST_PART *first_part;
746  OVERFLOW_REST_PART *rest_parts;
747  PAGE_PTR pgptr = NULL;
748  char *copyfrom;
749  VPID next_vpid;
750  int copy_length;
751  char *data;
752 
753  /*
754  * We don't need to lock the overflow pages since these pages are not
755  * shared among several pieces of overflow data. The overflow pages are
756  * know by accessing the relocation-overflow record with the appropiate lock
757  */
758 
759  next_vpid = *ovf_vpid;
760 
761  pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
762  if (pgptr == NULL)
763  {
764  return S_ERROR;
765  }
766 
767  (void) pgbuf_check_page_ptype (thread_p, pgptr, PAGE_OVERFLOW);
768 
769  first_part = (OVERFLOW_FIRST_PART *) pgptr;
770  if (mvcc_snapshot != NULL)
771  {
772  MVCC_REC_HEADER mvcc_header;
773  heap_get_mvcc_rec_header_from_overflow (pgptr, &mvcc_header, NULL);
774  if (mvcc_snapshot->snapshot_fnc (thread_p, &mvcc_header, mvcc_snapshot) == TOO_OLD_FOR_SNAPSHOT)
775  {
776  /* consider snapshot is not satisified only in case of TOO_OLD_FOR_SNAPSHOT;
777  * TOO_NEW_FOR_SNAPSHOT records should be accepted, e.g. a recently updated record, locked at select */
778  pgbuf_unfix_and_init (thread_p, pgptr);
780  }
781  }
782 
783  *remaining_length = first_part->length;
784 
785  if (max_nbytes < 0)
786  {
787  /* The rest of the overflow record starting at start_offset */
788  max_nbytes = *remaining_length - start_offset;
789  }
790  else
791  {
792  /* Don't give more than what we have */
793  if (max_nbytes > (*remaining_length - start_offset))
794  {
795  max_nbytes = *remaining_length - start_offset;
796  }
797  }
798 
799  if (max_nbytes < 0)
800  {
801  /* Likely the offset was beyond the size of the overflow record */
802  max_nbytes = 0;
803  *remaining_length = 0;
804  }
805  else
806  {
807  *remaining_length -= max_nbytes;
808  }
809 
810  /* Make sure that there is enough space to copy the desired length object */
811  if (max_nbytes > recdes->area_size)
812  {
813  pgbuf_unfix_and_init (thread_p, pgptr);
814 
815  /* Give a hint to the user of the needed length. Hint is given as a negative value */
816  recdes->length = -max_nbytes;
817  return S_DOESNT_FIT;
818  }
819  else if (max_nbytes == 0)
820  {
821  pgbuf_unfix_and_init (thread_p, pgptr);
822 
823  recdes->length = 0;
824  return S_SUCCESS;
825  }
826 
827  recdes->length = max_nbytes;
828 
829  /* Start copying the object */
830  data = recdes->data;
831  copyfrom = (char *) first_part->data;
832  next_vpid = first_part->next_vpid;
833 
834  while (max_nbytes > 0)
835  {
836  /* Continue seeking until the starting offset is reached (passed) */
837  if (start_offset > 0)
838  {
839  /* Advance .. seek as much as you can */
840  copy_length = (int) ((copyfrom + start_offset) > ((char *) pgptr + DB_PAGESIZE)
841  ? DB_PAGESIZE - (copyfrom - (char *) pgptr) : start_offset);
842  start_offset -= copy_length;
843  copyfrom += copy_length;
844  }
845 
846  /*
847  * Copy as much as you can when you do not need to continue seeking,
848  * and there is something to copy in current page (i.e., not at end
849  * of the page) and we are not located at the end of the overflow record.
850  */
851  if (start_offset == 0)
852  {
853  if (copyfrom + max_nbytes > (char *) pgptr + DB_PAGESIZE)
854  {
855  copy_length = DB_PAGESIZE - CAST_BUFLEN (copyfrom - (char *) pgptr);
856  }
857  else
858  {
859  copy_length = max_nbytes;
860  }
861 
862  /* If we were not at the end of the page, perform the copy */
863  if (copy_length > 0)
864  {
865  memcpy (data, copyfrom, copy_length);
866  data += copy_length;
867  max_nbytes -= copy_length;
868  }
869  }
870 
871  pgbuf_unfix_and_init (thread_p, pgptr);
872  if (max_nbytes > 0)
873  {
874  if (VPID_ISNULL (&next_vpid))
875  {
877  ovf_vpid->pageid, NULL_SLOTID);
878  return S_ERROR;
879  }
880 
881  pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
882  if (pgptr == NULL)
883  {
884  recdes->length = 0;
885  return S_ERROR;
886  }
887 
888  (void) pgbuf_check_page_ptype (thread_p, pgptr, PAGE_OVERFLOW);
889 
890  rest_parts = (OVERFLOW_REST_PART *) pgptr;
891  copyfrom = (char *) rest_parts->data;
892  next_vpid = rest_parts->next_vpid;
893  }
894  }
895 
896  return S_SUCCESS;
897 }
898 
899 /*
900  * overflow_get () - Get the content of a multipage object from overflow
901  * return: scan status
902  * ovf_vpid(in): Overflow address
903  * recdes(in): Record descriptor
904  * mvcc_snapshot(in): mvcc snapshot
905  *
906  * Note: The content of a multipage object associated with the given overflow
907  * address(oid) is placed into the area pointed to by the record
908  * descriptor. If the content of the object does not fit in such an area
909  * (i.e., recdes->area_size), an error is returned and a hint of its
910  * length is returned as a negative value in recdes->length. The length
911  * of the retrieved object is set in the the record descriptor
912  * (i.e., recdes->length).
913  *
914  */
915 SCAN_CODE
917 {
918  int remaining_length;
919 
920  return overflow_get_nbytes (thread_p, ovf_vpid, recdes, 0, -1, &remaining_length, mvcc_snapshot);
921 }
922 
923 /*
924  * overflow_get_capacity () - Find the current storage facts/capacity of given
925  * overflow rec
926  * return: NO_ERROR
927  * ovf_vpid(in): Overflow address
928  * ovf_size(out): Length of overflow object
929  * ovf_num_pages(out): Total number of overflow pages
930  * ovf_overhead(out): System overhead for overflow record
931  * ovf_free_space(out): Free space for exapnsion of the overflow rec
932  */
933 int
934 overflow_get_capacity (THREAD_ENTRY * thread_p, const VPID * ovf_vpid, int *ovf_size, int *ovf_num_pages,
935  int *ovf_overhead, int *ovf_free_space)
936 {
937  OVERFLOW_FIRST_PART *first_part;
938  OVERFLOW_REST_PART *rest_parts;
939  PAGE_PTR pgptr = NULL;
940  VPID next_vpid;
941  int remain_length;
942  int hdr_length;
943  int ret = NO_ERROR;
944 
945  /*
946  * We don't need to lock the overflow pages since these pages are not
947  * shared among several pieces of overflow data. The overflow pages are
948  * know by accessing the relocation-overflow record with the appropiate lock
949  */
950 
951  next_vpid = *ovf_vpid;
952 
953  pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
954  if (pgptr == NULL)
955  {
956  return ER_FAILED;
957  }
958 
959  (void) pgbuf_check_page_ptype (thread_p, pgptr, PAGE_OVERFLOW);
960 
961  first_part = (OVERFLOW_FIRST_PART *) pgptr;
962  remain_length = first_part->length;
963 
964  *ovf_size = first_part->length;
965  *ovf_num_pages = 0;
966  *ovf_overhead = 0;
967  *ovf_free_space = 0;
968 
969  hdr_length = offsetof (OVERFLOW_FIRST_PART, data);
970 
971  next_vpid = first_part->next_vpid;
972 
973  while (remain_length > 0)
974  {
975  if (remain_length > DB_PAGESIZE)
976  {
977  remain_length -= DB_PAGESIZE - hdr_length;
978  }
979  else
980  {
981  *ovf_free_space = DB_PAGESIZE - remain_length;
982  remain_length = 0;
983  }
984 
985  *ovf_num_pages += 1;
986  *ovf_overhead += hdr_length;
987 
988  if (remain_length > 0)
989  {
990  pgbuf_unfix_and_init (thread_p, pgptr);
991  if (VPID_ISNULL (&next_vpid))
992  {
994  ovf_vpid->pageid, NULL_SLOTID);
996  goto exit_on_error;
997  }
998 
999  pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
1000  if (pgptr == NULL)
1001  {
1002  goto exit_on_error;
1003  }
1004 
1005  (void) pgbuf_check_page_ptype (thread_p, pgptr, PAGE_OVERFLOW);
1006 
1007  rest_parts = (OVERFLOW_REST_PART *) pgptr;
1008  hdr_length = offsetof (OVERFLOW_REST_PART, data);
1009  next_vpid = rest_parts->next_vpid;
1010  }
1011  }
1012 
1013  pgbuf_unfix_and_init (thread_p, pgptr);
1014 
1015  return ret;
1016 
1017 exit_on_error:
1018 
1019  *ovf_size = 0;
1020  *ovf_num_pages = 0;
1021  *ovf_overhead = 0;
1022  *ovf_free_space = 0;
1023 
1024  return (ret == NO_ERROR && (ret = er_errid ()) == NO_ERROR) ? ER_FAILED : ret;
1025 }
1026 
1027 #if defined (CUBRID_DEBUG)
1028 /*
1029  * overflow_dump () - Dump an overflow object in ascii
1030  * return: NO_ERROR
1031  * ovf_vpid(in): Overflow address
1032  */
1033 int
1034 overflow_dump (THREAD_ENTRY * thread_p, FILE * fp, VPID * ovf_vpid)
1035 {
1036  OVERFLOW_FIRST_PART *first_part;
1037  OVERFLOW_REST_PART *rest_parts;
1038  PAGE_PTR pgptr = NULL;
1039  VPID next_vpid;
1040  int remain_length, dump_length;
1041  char *dumpfrom;
1042  int i;
1043  int ret = NO_ERROR;
1044 
1045  /*
1046  * We don't need to lock the overflow pages since these pages are not
1047  * shared among several pieces of overflow data. The overflow pages are
1048  * know by accessing the relocation-overflow record with the appropiate lock
1049  */
1050 
1051  next_vpid = *ovf_vpid;
1052  pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
1053  if (pgptr == NULL)
1054  {
1055  return ((ret = er_errid ()) == NO_ERROR) ? ER_FAILED : ret;
1056  }
1057 
1058  first_part = (OVERFLOW_FIRST_PART *) pgptr;
1059  remain_length = first_part->length;
1060  dumpfrom = (char *) first_part->data;
1061  next_vpid = first_part->next_vpid;
1062 
1063  while (remain_length > 0)
1064  {
1065  dump_length = (int) ((dumpfrom + remain_length > (char *) pgptr + DB_PAGESIZE)
1066  ? DB_PAGESIZE - (dumpfrom - (char *) pgptr) : remain_length);
1067  for (i = 0; i < dump_length; i++)
1068  {
1069  (void) fputc (*dumpfrom++, fp);
1070  }
1071 
1072  remain_length -= dump_length;
1073 
1074  if (remain_length > 0)
1075  {
1076  pgbuf_unfix_and_init (thread_p, pgptr);
1077  if (VPID_ISNULL (&next_vpid))
1078  {
1080  ovf_vpid->pageid, NULL_SLOTID);
1082  }
1083 
1084  pgptr = pgbuf_fix (thread_p, &next_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
1085  if (pgptr == NULL)
1086  {
1087  return ((ret = er_errid ()) == NO_ERROR) ? ER_FAILED : ret;
1088  }
1089 
1090  rest_parts = (OVERFLOW_REST_PART *) pgptr;
1091  dumpfrom = (char *) rest_parts->data;
1092  next_vpid = rest_parts->next_vpid;
1093  }
1094  }
1095 
1096  pgbuf_unfix_and_init (thread_p, pgptr);
1097 
1098  return ret;
1099 }
1100 #endif
1101 
1102 /*
1103  * overflow_rv_newpage_insert_redo () -
1104  * return: 0 if no error, or error code
1105  * rcv(in): Recovery structure
1106  */
1107 int
1109 {
1110  return log_rv_copy_char (thread_p, rcv);
1111 }
1112 
1113 /*
1114  * overflow_rv_newpage_link_undo () - Undo allocation of new overflow page and the
1115  * reference to it
1116  * return: 0 if no error, or error code
1117  * rcv(in): Recovery structure
1118  */
1119 int
1121 {
1122  OVERFLOW_REST_PART *rest_parts;
1123 
1124  rest_parts = (OVERFLOW_REST_PART *) rcv->pgptr;
1125  VPID_SET_NULL (&rest_parts->next_vpid);
1126  pgbuf_set_dirty (thread_p, rcv->pgptr, DONT_FREE);
1127 
1128  return NO_ERROR;
1129 }
1130 
1131 /*
1132  * overflow_rv_link () - Recover overflow
1133  * return: 0 if no error, or error code
1134  * rcv(in): Recovery structure
1135  *
1136  * Note: It can be used for undo a new allocation of overflow page or for redo
1137  * deallocation of overflow page
1138  */
1139 int
1141 {
1142  VPID *vpid;
1143  OVERFLOW_REST_PART *rest_parts;
1144 
1145  vpid = (VPID *) rcv->data;
1146  rest_parts = (OVERFLOW_REST_PART *) rcv->pgptr;
1147  rest_parts->next_vpid = *vpid;
1148  pgbuf_set_dirty (thread_p, rcv->pgptr, DONT_FREE);
1149 
1150  return NO_ERROR;
1151 }
1152 
1153 /*
1154  * overflow_rv_link_dump () - Dump recovery information related to overflow link
1155  * return: void
1156  * length_ignore(in): Length of Recovery Data
1157  * data(in): The data being logged
1158  */
1159 void
1160 overflow_rv_link_dump (FILE * fp, int length_ignore, void *data)
1161 {
1162  VPID *vpid;
1163 
1164  vpid = (VPID *) data;
1165  fprintf (fp, "Overflow Reference to Volid = %d|Pageid = %d\n", vpid->volid, vpid->pageid);
1166 }
1167 
1168 /*
1169  * overflow_rv_page_update_redo () -
1170  * return: 0 if no error, or error code
1171  * rcv(in): Recovery structure
1172  */
1173 int
1175 {
1176  (void) pgbuf_set_page_ptype (thread_p, rcv->pgptr, PAGE_OVERFLOW);
1177 
1178  return log_rv_copy_char (thread_p, rcv);
1179 }
1180 
1181 /*
1182  * overflow_rv_page_dump () - Dump overflow page
1183  * return: void
1184  * length_ignore(in): Length of Recovery Data
1185  * data(in): The data being logged
1186  */
1187 void
1188 overflow_rv_page_dump (FILE * fp, int length, void *data)
1189 {
1190  OVERFLOW_REST_PART *rest_parts;
1191  char *dumpfrom;
1192  int hdr_length;
1193 
1194  rest_parts = (OVERFLOW_REST_PART *) data;
1195  fprintf (fp, "Overflow Link to Volid = %d|Pageid = %d\n", rest_parts->next_vpid.volid, rest_parts->next_vpid.pageid);
1196  dumpfrom = (char *) data;
1197 
1198  hdr_length = offsetof (OVERFLOW_REST_PART, data);
1199  length -= hdr_length;
1200  dumpfrom += hdr_length;
1201 
1202  log_rv_dump_char (fp, length, (void *) dumpfrom);
1203 }
1204 
1205 /*
1206  * overflow_get_first_page_data () - get data of overflow first page
1207  *
1208  * return: overflow first page data data
1209  * page_ptr(in): overflow page
1210  *
1211  */
1212 char *
1214 {
1215  assert (page_ptr != NULL);
1216  return ((OVERFLOW_FIRST_PART *) page_ptr)->data;
1217 }
char * PAGE_PTR
int overflow_rv_newpage_link_undo(THREAD_ENTRY *thread_p, LOG_RCV *rcv)
int overflow_rv_link(THREAD_ENTRY *thread_p, LOG_RCV *rcv)
int overflow_rv_newpage_insert_redo(THREAD_ENTRY *thread_p, LOG_RCV *rcv)
#define NO_ERROR
Definition: error_code.h:46
int area_size
void log_append_redo_data(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, LOG_DATA_ADDR *addr, int length, const void *data)
Definition: log_manager.c:1979
int file_init_temp_page_type(THREAD_ENTRY *thread_p, PAGE_PTR page, void *args)
static int overflow_delete_internal(THREAD_ENTRY *thread_p, const VFID *ovf_vfid, VPID *vpid, PAGE_PTR pgptr)
#define ASSERT_ERROR()
SCAN_CODE
int file_dealloc(THREAD_ENTRY *thread_p, const VFID *vfid, const VPID *vpid, FILE_TYPE file_type_hint)
int file_alloc_multiple(THREAD_ENTRY *thread_p, const VFID *vfid, FILE_INIT_PAGE_FUNC f_init, void *f_init_args, int npages, VPID *vpids_out)
#define ER_FAILED
Definition: error_code.h:47
FILE_TYPE
Definition: file_manager.h:38
#define ASSERT_ERROR_AND_SET(error_code)
void pgbuf_set_dirty(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, bool free_page)
Definition: page_buffer.c:4280
char * overflow_get_first_page_data(char *page_ptr)
SCAN_CODE overflow_get(THREAD_ENTRY *thread_p, const VPID *ovf_vpid, RECDES *recdes, MVCC_SNAPSHOT *mvcc_snapshot)
void log_sysop_start(THREAD_ENTRY *thread_p)
Definition: log_manager.c:3578
#define NULL_SLOTID
char * data
int32_t pageid
Definition: dbtype_def.h:879
void overflow_rv_link_dump(FILE *fp, int length_ignore, void *data)
PAGE_PTR pgbuf_flush_with_wal(THREAD_ENTRY *thread_p, PAGE_PTR pgptr)
Definition: page_buffer.c:2956
int er_errid(void)
PAGE_TYPE
#define OVERFLOW_ALLOCVPID_ARRAY_SIZE
Definition: overflow_file.c:41
#define er_log_debug(...)
#define VFID_ISNULL(vfid_ptr)
Definition: file_manager.h:72
void THREAD_ENTRY
int overflow_update(THREAD_ENTRY *thread_p, const VFID *ovf_vfid, const VPID *ovf_vpid, RECDES *recdes, FILE_TYPE file_type)
#define pgbuf_unfix_and_init(thread_p, pgptr)
Definition: page_buffer.h:63
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
PAGE_PTR pgptr
Definition: recovery.h:199
int log_rv_copy_char(THREAD_ENTRY *thread_p, LOG_RCV *rcv)
Definition: log_manager.c:8696
#define assert(x)
int heap_get_mvcc_rec_header_from_overflow(PAGE_PTR ovf_page, MVCC_REC_HEADER *mvcc_header, RECDES *peek_recdes)
Definition: heap_file.c:18714
bool pgbuf_check_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, PAGE_TYPE ptype)
#define pgbuf_set_dirty_and_free(thread_p, pgptr)
Definition: page_buffer.h:351
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
void log_append_undo_data(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, LOG_DATA_ADDR *addr, int length, const void *data)
Definition: log_manager.c:1917
#define ER_HEAP_OVFADDRESS_CORRUPTED
Definition: error_code.h:106
#define VPID_EQ(vpid_ptr1, vpid_ptr2)
Definition: dbtype_def.h:915
short volid
Definition: dbtype_def.h:880
int overflow_get_capacity(THREAD_ENTRY *thread_p, const VPID *ovf_vpid, int *ovf_size, int *ovf_num_pages, int *ovf_overhead, int *ovf_free_space)
#define NULL
Definition: freelistheap.h:34
int file_alloc(THREAD_ENTRY *thread_p, const VFID *vfid, FILE_INIT_PAGE_FUNC f_init, void *f_init_args, VPID *vpid_out, PAGE_PTR *page_out)
const VFID * vfid
Definition: log_append.hpp:56
PAGE_PTR pgptr
Definition: log_append.hpp:57
void log_append_undoredo_data(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, LOG_DATA_ADDR *addr, int undo_length, int redo_length, const void *undo_data, const void *redo_data)
Definition: log_manager.c:1837
#define pgbuf_fix(thread_p, vpid, fetch_mode, requestmode, condition)
Definition: page_buffer.h:255
#define CEIL_PTVDIV(dividend, divisor)
Definition: memory_alloc.h:50
offset_type offset
Definition: log_append.hpp:58
void log_sysop_abort(THREAD_ENTRY *thread_p)
Definition: log_manager.c:4017
#define CAST_BUFLEN
Definition: porting.h:471
int file_init_page_type(THREAD_ENTRY *thread_p, PAGE_PTR page, void *args)
#define VPID_ISNULL(vpid_ptr)
Definition: dbtype_def.h:925
const char * data
Definition: recovery.h:203
void overflow_flush(THREAD_ENTRY *thread_p, const VPID *ovf_vpid)
#define ARG_FILE_LINE
Definition: error_manager.h:44
static const VPID * overflow_traverse(THREAD_ENTRY *thread_p, const VFID *ovf_vfid, const VPID *ovf_vpid, OVERFLOW_DO_FUNC func)
static void overflow_next_vpid(const VPID *ovf_vpid, VPID *vpid, PAGE_PTR pgptr)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
struct vpid VPID
Definition: dbtype_def.h:876
#define DB_PAGESIZE
void log_append_empty_record(THREAD_ENTRY *thread_p, LOG_RECTYPE logrec_type, LOG_DATA_ADDR *addr)
Definition: log_manager.c:3117
void log_rv_dump_char(FILE *fp, int length, void *data)
Definition: log_manager.c:8719
void pgbuf_set_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, PAGE_TYPE ptype)
Definition: page_buffer.c:4847
void log_sysop_attach_to_outer(THREAD_ENTRY *thread_p)
Definition: log_manager.c:4076
int i
Definition: dynamic_load.c:954
int overflow_rv_page_update_redo(THREAD_ENTRY *thread_p, LOG_RCV *rcv)
while(1)
Definition: cnvlex.c:816
MVCC_SNAPSHOT_FUNC snapshot_fnc
Definition: mvcc.h:176
#define DONT_FREE
Definition: page_buffer.h:41
OVERFLOW_DO_FUNC
Definition: overflow_file.c:58
void overflow_rv_page_dump(FILE *fp, int length, void *data)
int overflow_get_length(THREAD_ENTRY *thread_p, const VPID *ovf_vpid)
int overflow_insert(THREAD_ENTRY *thread_p, const VFID *ovf_vfid, VPID *ovf_vpid, RECDES *recdes, FILE_TYPE file_type)
Definition: overflow_file.c:95
#define VPID_SET_NULL(vpid_ptr)
Definition: dbtype_def.h:906
static int overflow_flush_internal(THREAD_ENTRY *thread_p, PAGE_PTR pgptr)
VPID * pgbuf_get_vpid_ptr(PAGE_PTR pgptr)
Definition: page_buffer.c:4609
const VPID * overflow_delete(THREAD_ENTRY *thread_p, const VFID *ovf_vfid, const VPID *ovf_vpid)
SCAN_CODE overflow_get_nbytes(THREAD_ENTRY *thread_p, const VPID *ovf_vpid, RECDES *recdes, int start_offset, int max_nbytes, int *remaining_length, MVCC_SNAPSHOT *mvcc_snapshot)