CUBRID Engine  latest
system_catalog.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  * system_catalog.c - Catalog manager
21  */
22 
23 #ident "$Id$"
24 
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include <time.h>
29 
30 #include "system_catalog.h"
31 
32 #include "error_manager.h"
33 #include "file_manager.h"
34 #include "log_append.hpp"
35 #include "slotted_page.h"
36 #include "extendible_hash.h"
37 #include "boot_sr.h"
38 #include "btree_load.h"
39 #include "heap_file.h"
40 #include "xserver_interface.h"
41 #include "statistics_sr.h"
42 #include "partition_sr.h"
43 #include "object_primitive.h"
44 #include "object_representation.h"
46 #include "thread_manager.hpp"
47 
48 #if !defined(SERVER_MODE)
49 #define pthread_mutex_init(a, b)
50 #define pthread_mutex_destroy(a)
51 #define pthread_mutex_lock(a) 0
52 #define pthread_mutex_trylock(a) 0
53 #define pthread_mutex_unlock(a)
54 static int rv;
55 #endif /* not SERVER_MODE */
56 
57 #define CATALOG_HEADER_SLOT 0
58 #define CATALOG_MAX_SLOT_ID_SIZE 12
59 #define CATALOG_HASH_SIZE 1000
60 #define CATALOG_KEY_VALUE_ARRAY_SIZE 1000
61 
62 #define CATALOG_PGHEADER_OVFL_PGID_PAGEID_OFF 0
63 #define CATALOG_PGHEADER_OVFL_PGID_VOLID_OFF 4
64 #define CATALOG_PGHEADER_DIR_CNT_OFF 8
65 #define CATALOG_PGHEADER_PG_OVFL_OFF 12
66 
67 #define CATALOG_PAGE_HEADER_SIZE 16
68 
69 /* READERS for CATALOG_PAGE_HEADER related fields */
70 #define CATALOG_GET_PGHEADER_OVFL_PGID_PAGEID(ptr) \
71  (PAGEID) OR_GET_INT ((ptr) + CATALOG_PGHEADER_OVFL_PGID_PAGEID_OFF)
72 
73 #define CATALOG_GET_PGHEADER_OVFL_PGID_VOLID(ptr) \
74  (VOLID) OR_GET_SHORT ((ptr) + CATALOG_PGHEADER_OVFL_PGID_VOLID_OFF)
75 
76 #define CATALOG_GET_PGHEADER_DIR_COUNT(ptr) \
77  (int) OR_GET_INT ((ptr) + CATALOG_PGHEADER_DIR_CNT_OFF)
78 
79 #define CATALOG_GET_PGHEADER_PG_OVFL(ptr) \
80  (bool) OR_GET_INT ((ptr) + CATALOG_PGHEADER_PG_OVFL_OFF)
81 
82 /* WRITERS for CATALOG_PAGE_HEADER related fields */
83 #define CATALOG_PUT_PGHEADER_OVFL_PGID_PAGEID(ptr,val) \
84  OR_PUT_INT ((ptr) + CATALOG_PGHEADER_OVFL_PGID_PAGEID_OFF, (val))
85 
86 #define CATALOG_PUT_PGHEADER_OVFL_PGID_VOLID(ptr,val) \
87  OR_PUT_SHORT ((ptr) + CATALOG_PGHEADER_OVFL_PGID_VOLID_OFF, (val))
88 
89 #define CATALOG_PUT_PGHEADER_DIR_COUNT(ptr,val) \
90  OR_PUT_INT ((ptr) + CATALOG_PGHEADER_DIR_CNT_OFF, (val))
91 
92 #define CATALOG_PUT_PGHEADER_PG_OVFL(ptr,val) \
93  OR_PUT_INT ((ptr) + CATALOG_PGHEADER_PG_OVFL_OFF, (int) (val))
94 
95 /* Each disk representation is aligned with MAX_ALIGNMENT */
96 #define CATALOG_DISK_REPR_ID_OFF 0
97 #define CATALOG_DISK_REPR_N_FIXED_OFF 4
98 #define CATALOG_DISK_REPR_FIXED_LENGTH_OFF 8
99 #define CATALOG_DISK_REPR_N_VARIABLE_OFF 12
100 #define CATALOG_DISK_REPR_RESERVED_1_OFF 16 /* reserved for future use */
101 #define CATALOG_DISK_REPR_SIZE 56
102 
103 /* Each disk attribute is aligned with MAX_ALIGNMENT
104  Each disk attribute may be followed by a "value" which is of
105  variable size. The below constants does not consider the
106  optional value field following the attribute structure. */
107 #define CATALOG_DISK_ATTR_ID_OFF 0
108 #define CATALOG_DISK_ATTR_LOCATION_OFF 4
109 #define CATALOG_DISK_ATTR_TYPE_OFF 8
110 #define CATALOG_DISK_ATTR_VAL_LENGTH_OFF 12
111 #define CATALOG_DISK_ATTR_POSITION_OFF 16
112 #define CATALOG_DISK_ATTR_CLASSOID_OFF 20
113 #define CATALOG_DISK_ATTR_N_BTSTATS_OFF 28
114 #define CATALOG_DISK_ATTR_SIZE 80
115 
116 #define CATALOG_BT_STATS_BTID_OFF 0
117 #define CATALOG_BT_STATS_LEAFS_OFF OR_BTID_ALIGNED_SIZE
118 #define CATALOG_BT_STATS_PAGES_OFF 16
119 #define CATALOG_BT_STATS_HEIGHT_OFF 20
120 #define CATALOG_BT_STATS_KEYS_OFF 24
121 #define CATALOG_BT_STATS_FUNC_INDEX_OFF 28
122 #define CATALOG_BT_STATS_PKEYS_OFF 32
123 #define CATALOG_BT_STATS_RESERVED_OFF (CATALOG_BT_STATS_PKEYS_OFF + (OR_INT_SIZE * BTREE_STATS_PKEYS_NUM)) /* 64 */
124 #define CATALOG_BT_STATS_SIZE (CATALOG_BT_STATS_RESERVED_OFF + (OR_INT_SIZE * BTREE_STATS_RESERVED_NUM)) /* 64 + (4 * R_NUM) = 80 */
125 
126 #define CATALOG_GET_BT_STATS_BTID(var, ptr) \
127  OR_GET_BTID((ptr) + CATALOG_BT_STATS_BTID_OFF, (var))
128 
129 #define CATALOG_CLS_INFO_HFID_OFF 0
130 #define CATALOG_CLS_INFO_TOT_PAGES_OFF 12
131 #define CATALOG_CLS_INFO_TOT_OBJS_OFF 16
132 #define CATALOG_CLS_INFO_TIME_STAMP_OFF 20
133 #define CATALOG_CLS_INFO_REP_DIR_OFF 24
134 #define CATALOG_CLS_INFO_SIZE 56
135 #define CATALOG_CLS_INFO_RESERVED 24
136 
137 #define CATALOG_REPR_ITEM_PAGEID_PAGEID_OFF 0
138 #define CATALOG_REPR_ITEM_PAGEID_VOLID_OFF 4
139 #define CATALOG_REPR_ITEM_REPRID_OFF 8
140 #define CATALOG_REPR_ITEM_SLOTID_OFF 10
141 #define CATALOG_REPR_ITEM_COUNT_OFF 12
142 
143 #define CATALOG_REPR_ITEM_SIZE 16
144 
145 #define CATALOG_GET_REPR_ITEM_PAGEID_PAGEID(ptr) \
146  (PAGEID) OR_GET_INT ((ptr) + CATALOG_REPR_ITEM_PAGEID_PAGEID_OFF)
147 
148 #define CATALOG_GET_REPR_ITEM_PAGEID_VOLID(ptr) \
149  (VOLID) OR_GET_SHORT ((ptr) + CATALOG_REPR_ITEM_PAGEID_VOLID_OFF)
150 
151 #define CATALOG_GET_REPR_ITEM_REPRID(ptr) \
152  (REPR_ID) OR_GET_SHORT ((ptr) + CATALOG_REPR_ITEM_REPRID_OFF)
153 
154 #define CATALOG_GET_REPR_ITEM_SLOTID(ptr) \
155  (PGSLOTID) OR_GET_SHORT ((ptr) + CATALOG_REPR_ITEM_SLOTID_OFF)
156 
157 #define CATALOG_GET_REPR_ITEM_COUNT(ptr) \
158  (PGSLOTID) OR_GET_BYTE ((ptr) + CATALOG_REPR_ITEM_COUNT_OFF)
159 
160 /* catalog estimated max. space information */
163 {
164  VPID max_page_id; /* estimated maximum space page identifier */
165  PGLENGTH max_space; /* estimated maximum space */
166 };
167 
168 /* catalog key for the hash table */
169 typedef struct catalog_key CATALOG_KEY;
171 {
172  /* actual key */
177 
178  /* these are part of the data, but we want them inserted atomically */
179  VPID r_page_id; /* location of representation */
181 }; /* class identifier + representation identifier */
182 
183 /* catalog value for the hash table */
186 {
187  CATALOG_ENTRY *stack; /* used for freelist */
188  CATALOG_ENTRY *next; /* next in hash chain */
189  UINT64 del_id; /* delete transaction ID (for lock free) */
190  CATALOG_KEY key; /* key of catalog entry */
191 };
192 
193 /* handling functions for catalog key and entry */
194 static void *catalog_entry_alloc (void);
195 static int catalog_entry_free (void *ent);
196 static int catalog_entry_init (void *ent);
197 static int catalog_entry_uninit (void *ent);
198 static int catalog_key_copy (void *src, void *dest);
199 static int catalog_key_compare (void *key1, void *key2);
200 static unsigned int catalog_key_hash (void *key, int htsize);
201 
202 /* catalog entry descriptor */
204  /* offsets */
205  offsetof (CATALOG_ENTRY, stack),
206  offsetof (CATALOG_ENTRY, next),
207  offsetof (CATALOG_ENTRY, del_id),
208  offsetof (CATALOG_ENTRY, key),
209  0,
210 
211  /* using mutex? */
213 
221  NULL /* no inserts */
222 };
223 
226 {
229 };
230 
233 {
234  VPID vpid; /* (volume id, page id) of the slotted page record */
235  PGSLOTID slotid; /* slot id of the slotted page record record */
236  PAGE_PTR page_p; /* pointer to the page fetched */
237  RECDES recdes; /* record descriptor to be fetched and copied */
238  int offset; /* offset in the record data */
239 };
240 
243 {
244  VPID overflow_page_id; /* overflow page identifier */
245  int dir_count; /* number of directories in page */
246  bool is_overflow_page; /* true if page is overflow page, false or else */
247 };
248 
251 {
252  VPID page_id; /* page identifier of the representation */
253  INT16 repr_id; /* representation identifier */
254  PGSLOTID slot_id; /* page slot identifier of representation */
255 };
256 
257 #define CATALOG_REPR_ITEM_INITIALIZER \
258  { { NULL_PAGEID, NULL_VOLID }, NULL_REPRID, NULL_SLOTID }
259 
260 CTID catalog_Id; /* global catalog identifier */
261 static PGLENGTH catalog_Max_record_size; /* Maximum Record Size */
262 
263 /*
264  * Note: Catalog memory hash table operations are NOT done in CRITICAL
265  * SECTIONS, because there can not be simultaneous updaters and readers
266  * for the same class representation information.
267  */
268 // *INDENT-OFF*
270 // *INDENT-ON*
272 
273 static CATALOG_MAX_SPACE catalog_Max_space; /* Global space information */
274 static pthread_mutex_t catalog_Max_space_lock = PTHREAD_MUTEX_INITIALIZER;
275 static bool catalog_is_header_initialized = false;
276 
279 {
280  int size;
284 };
285 
286 #if defined (SA_MODE)
287 typedef struct catalog_page_collector CATALOG_PAGE_COLLECTOR;
288 struct catalog_page_collector
289 {
290  VPID *vpids;
291  int n_vpids;
292 };
293 #endif /* SA_MODE */
294 
297 {
298  FILE *fp;
300 };
301 
302 static void catalog_initialize_max_space (CATALOG_MAX_SPACE * header_p);
303 static void catalog_update_max_space (VPID * page_id, PGLENGTH space);
304 
305 static int catalog_initialize_new_page (THREAD_ENTRY * thread_p, PAGE_PTR page, void *args);
306 static PAGE_PTR catalog_get_new_page (THREAD_ENTRY * thread_p, VPID * page_id, bool is_overflow_page);
307 static PAGE_PTR catalog_find_optimal_page (THREAD_ENTRY * thread_p, int size, VPID * page_id);
308 static int catalog_get_key_list (THREAD_ENTRY * thread_p, void *key, void *val, void *args);
309 static void catalog_free_key_list (CATALOG_CLASS_ID_LIST * clsid_list);
310 static int catalog_put_record_into_page (THREAD_ENTRY * thread_p, CATALOG_RECORD * ct_recordp, int next,
311  PGSLOTID * remembered_slotid);
312 static int catalog_store_disk_representation (THREAD_ENTRY * thread_p, DISK_REPR * disk_reprp,
313  CATALOG_RECORD * ct_recordp, PGSLOTID * remembered_slotid);
314 static int catalog_store_disk_attribute (THREAD_ENTRY * thread_p, DISK_ATTR * disk_attrp, CATALOG_RECORD * ct_recordp,
315  PGSLOTID * remembered_slotid);
316 static int catalog_store_attribute_value (THREAD_ENTRY * thread_p, void *value, int length, CATALOG_RECORD * ct_recordp,
317  PGSLOTID * remembered_slotid);
318 static int catalog_store_btree_statistics (THREAD_ENTRY * thread_p, BTREE_STATS * bt_statsp,
319  CATALOG_RECORD * ct_recordp, PGSLOTID * remembered_slotid);
320 static int catalog_get_record_from_page (THREAD_ENTRY * thread_p, CATALOG_RECORD * ct_recordp);
321 static int catalog_fetch_disk_representation (THREAD_ENTRY * thread_p, DISK_REPR * disk_reprp,
322  CATALOG_RECORD * ct_recordp);
323 static int catalog_fetch_disk_attribute (THREAD_ENTRY * thread_p, DISK_ATTR * disk_attrp, CATALOG_RECORD * ct_recordp);
324 static int catalog_fetch_attribute_value (THREAD_ENTRY * thread_p, void *value, int length,
325  CATALOG_RECORD * ct_recordp);
326 static int catalog_fetch_btree_statistics (THREAD_ENTRY * thread_p, BTREE_STATS * bt_statsp,
327  CATALOG_RECORD * ct_recordp);
328 static int catalog_drop_disk_representation_from_page (THREAD_ENTRY * thread_p, VPID * page_id, PGSLOTID slot_id);
329 static int catalog_drop_representation_class_from_page (THREAD_ENTRY * thread_p, VPID * dir_pgid, PAGE_PTR * dir_pgptr,
330  VPID * page_id, PGSLOTID slot_id);
331 static int catalog_get_rep_dir (THREAD_ENTRY * thread_p, OID * class_oid_p, OID * rep_dir_p, bool lookup_hash);
332 static PAGE_PTR catalog_get_representation_record (THREAD_ENTRY * thread_p, OID * rep_dir_p, RECDES * record_p,
333  PGBUF_LATCH_MODE latch, int is_peek, int *out_repr_count_p);
335  RECDES * record_p, PGBUF_LATCH_MODE latch, int is_peek,
336  OID * rep_dir_p, int *out_repr_count_p,
337  bool lookup_hash);
338 static int catalog_adjust_directory_count (THREAD_ENTRY * thread_p, PAGE_PTR page_p, RECDES * record_p, int delta);
339 static void catalog_delete_key (THREAD_ENTRY * thread_p, OID * class_id_p, REPR_ID repr_id);
340 static char *catalog_find_representation_item_position (INT16 repr_id, int repr_cnt, char *repr_p, int *out_position_p);
341 static int catalog_insert_representation_item (THREAD_ENTRY * thread_p, RECDES * record_p, OID * rep_dir_p);
342 static int catalog_drop_directory (THREAD_ENTRY * thread_p, PAGE_PTR page_p, RECDES * record_p, OID * oid_p,
343  OID * class_id_p);
344 static void catalog_copy_btree_statistic (BTREE_STATS * new_btree_stats_p, int new_btree_stats_count,
345  BTREE_STATS * pre_btree_stats_p, int pre_btree_stats_count);
346 static void catalog_copy_disk_attributes (DISK_ATTR * new_attrs_p, int new_attr_count, DISK_ATTR * pre_attrs_p,
347  int pre_attr_count);
348 static int catalog_sum_disk_attribute_size (DISK_ATTR * attrs_p, int count);
349 
350 static int catalog_put_representation_item (THREAD_ENTRY * thread_p, OID * class_id, CATALOG_REPR_ITEM * repr_item,
351  OID * rep_dir_p);
352 static int catalog_get_representation_item (THREAD_ENTRY * thread_p, OID * class_id, CATALOG_REPR_ITEM * repr_item);
353 static int catalog_drop_representation_item (THREAD_ENTRY * thread_p, OID * class_id, CATALOG_REPR_ITEM * repr_item);
354 static int catalog_drop (THREAD_ENTRY * thread_p, OID * class_id, REPR_ID repr_id);
355 static int catalog_drop_all (THREAD_ENTRY * thread_p, OID * class_id);
357 #if defined (ENABLE_UNUSED_FUNCTION)
358 static int catalog_fixup_missing_disk_representation (THREAD_ENTRY * thread_p, OID * class_oid, REPR_ID reprid);
359 static int catalog_fixup_missing_class_info (THREAD_ENTRY * thread_p, OID * class_oid);
360 #endif
361 static DISK_ISVALID catalog_check_class_consistency (THREAD_ENTRY * thread_p, OID * class_oid);
362 static void catalog_dump_disk_attribute (DISK_ATTR * atr);
363 static void catalog_dump_representation (DISK_REPR * dr);
364 static void catalog_clear_hash_table (THREAD_ENTRY * thread_p);
365 
366 static void catalog_put_page_header (char *rec_p, CATALOG_PAGE_HEADER * header_p);
367 static void catalog_get_disk_representation (DISK_REPR * disk_repr_p, char *rec_p);
368 static void catalog_put_disk_representation (char *rec_p, DISK_REPR * disk_repr_p);
369 static void catalog_get_disk_attribute (DISK_ATTR * attr_p, char *rec_p);
370 static void catalog_put_disk_attribute (char *rec_p, DISK_ATTR * attr_p);
371 static void catalog_put_btree_statistics (char *rec_p, BTREE_STATS * stat_p);
372 static void catalog_get_class_info_from_record (CLS_INFO * class_info_p, char *rec_p);
373 static void catalog_put_class_info_to_record (char *rec_p, CLS_INFO * class_info_p);
374 static void catalog_get_repr_item_from_record (CATALOG_REPR_ITEM * item_p, char *rec_p);
375 static void catalog_put_repr_item_to_record (char *rec_p, CATALOG_REPR_ITEM * item_p);
376 static int catalog_assign_attribute (THREAD_ENTRY * thread_p, DISK_ATTR * disk_attr_p,
377  CATALOG_RECORD * catalog_record_p);
378 
379 #if defined (SA_MODE)
380 static int catalog_file_map_is_empty (THREAD_ENTRY * thread_p, PAGE_PTR * page, bool * stop, void *args);
381 #endif /* SA_MODE */
382 static int catalog_file_map_page_dump (THREAD_ENTRY * thread_p, PAGE_PTR * page, bool * stop, void *args);
383 static int catalog_file_map_overflow_count (THREAD_ENTRY * thread_p, PAGE_PTR * page, bool * stop, void *args);
384 
385 static void
387 {
390  CATALOG_PUT_PGHEADER_DIR_COUNT (rec_p, header_p->dir_count);
392 }
393 
394 static void
395 catalog_get_disk_representation (DISK_REPR * disk_repr_p, char *rec_p)
396 {
397  disk_repr_p->id = (REPR_ID) OR_GET_INT (rec_p + CATALOG_DISK_REPR_ID_OFF);
398  disk_repr_p->n_fixed = OR_GET_INT (rec_p + CATALOG_DISK_REPR_N_FIXED_OFF);
399  disk_repr_p->fixed = NULL;
401  disk_repr_p->n_variable = OR_GET_INT (rec_p + CATALOG_DISK_REPR_N_VARIABLE_OFF);
402  disk_repr_p->variable = NULL;
403 
404 #if 0 /* reserved for future use */
405  disk_repr_p->repr_reserved_1 = OR_GET_INT (rec_p + CATALOG_DISK_REPR_RESERVED_1_OFF);
406 #endif
407 }
408 
409 static void
410 catalog_put_disk_representation (char *rec_p, DISK_REPR * disk_repr_p)
411 {
412  OR_PUT_INT (rec_p + CATALOG_DISK_REPR_ID_OFF, disk_repr_p->id);
413  OR_PUT_INT (rec_p + CATALOG_DISK_REPR_N_FIXED_OFF, disk_repr_p->n_fixed);
416 
417 #if 1 /* reserved for future use */
419 #endif
420 }
421 
422 static void
423 catalog_get_disk_attribute (DISK_ATTR * attr_p, char *rec_p)
424 {
425  attr_p->id = OR_GET_INT (rec_p + CATALOG_DISK_ATTR_ID_OFF);
427  attr_p->type = (DB_TYPE) OR_GET_INT (rec_p + CATALOG_DISK_ATTR_TYPE_OFF);
428  attr_p->value = NULL;
433  attr_p->bt_stats = NULL;
434 }
435 
436 static void
438 {
439  int i;
440 
441  stat_p->leafs = OR_GET_INT (rec_p + CATALOG_BT_STATS_LEAFS_OFF);
442  stat_p->pages = OR_GET_INT (rec_p + CATALOG_BT_STATS_PAGES_OFF);
443  stat_p->height = OR_GET_INT (rec_p + CATALOG_BT_STATS_HEIGHT_OFF);
444  stat_p->keys = OR_GET_INT (rec_p + CATALOG_BT_STATS_KEYS_OFF);
446 
448  for (i = 0; i < stat_p->pkeys_size; i++)
449  {
450  stat_p->pkeys[i] = OR_GET_INT (rec_p + CATALOG_BT_STATS_PKEYS_OFF + (OR_INT_SIZE * i));
451  }
452 #if 0 /* reserved for future use */
453  for (i = 0; i < BTREE_STATS_RESERVED_NUM; i++)
454  {
455  stat_p->reserved[i] = OR_GET_INT (rec_p + CATALOG_BT_STATS_RESERVED_OFF + (OR_INT_SIZE * i));
456  }
457 #endif
458 }
459 
460 static void
461 catalog_put_disk_attribute (char *rec_p, DISK_ATTR * attr_p)
462 {
463  OR_PUT_INT (rec_p + CATALOG_DISK_ATTR_ID_OFF, attr_p->id);
465  OR_PUT_INT (rec_p + CATALOG_DISK_ATTR_TYPE_OFF, attr_p->type);
468 
471 }
472 
473 static void
475 {
476  int i;
477 
478  OR_PUT_BTID (rec_p + CATALOG_BT_STATS_BTID_OFF, &stat_p->btid);
479  OR_PUT_INT (rec_p + CATALOG_BT_STATS_LEAFS_OFF, stat_p->leafs);
480  OR_PUT_INT (rec_p + CATALOG_BT_STATS_PAGES_OFF, stat_p->pages);
481  OR_PUT_INT (rec_p + CATALOG_BT_STATS_HEIGHT_OFF, stat_p->height);
482  OR_PUT_INT (rec_p + CATALOG_BT_STATS_KEYS_OFF, stat_p->keys);
484 
486  for (i = 0; i < stat_p->pkeys_size; i++)
487  {
488  OR_PUT_INT (rec_p + CATALOG_BT_STATS_PKEYS_OFF + (OR_INT_SIZE * i), stat_p->pkeys[i]);
489  }
490 
491 #if 1 /* reserved for future use */
492  for (i = 0; i < BTREE_STATS_RESERVED_NUM; i++)
493  {
495  }
496 #endif
497 }
498 
499 static void
500 catalog_get_class_info_from_record (CLS_INFO * class_info_p, char *rec_p)
501 {
502  OR_GET_HFID (rec_p + CATALOG_CLS_INFO_HFID_OFF, &class_info_p->ci_hfid);
503 
504  class_info_p->ci_tot_pages = OR_GET_INT (rec_p + CATALOG_CLS_INFO_TOT_PAGES_OFF);
505  class_info_p->ci_tot_objects = OR_GET_INT (rec_p + CATALOG_CLS_INFO_TOT_OBJS_OFF);
506  class_info_p->ci_time_stamp = OR_GET_INT (rec_p + CATALOG_CLS_INFO_TIME_STAMP_OFF);
507 
508  OR_GET_OID (rec_p + CATALOG_CLS_INFO_REP_DIR_OFF, &(class_info_p->ci_rep_dir));
509  assert (!OID_ISNULL (&(class_info_p->ci_rep_dir)));
510 }
511 
512 static void
513 catalog_put_class_info_to_record (char *rec_p, CLS_INFO * class_info_p)
514 {
515  assert (!OID_ISNULL (&(class_info_p->ci_rep_dir)));
516 
517  OR_PUT_HFID (rec_p + CATALOG_CLS_INFO_HFID_OFF, &class_info_p->ci_hfid);
518 
519  OR_PUT_INT (rec_p + CATALOG_CLS_INFO_TOT_PAGES_OFF, class_info_p->ci_tot_pages);
522 
523  OR_PUT_OID (rec_p + CATALOG_CLS_INFO_REP_DIR_OFF, &(class_info_p->ci_rep_dir));
524 }
525 
526 static void
528 {
533 }
534 
535 static void
537 {
542 }
543 
544 static void
546 {
547  int rv;
549 
550  max_space_p->max_page_id.pageid = NULL_PAGEID;
551  max_space_p->max_page_id.volid = NULL_VOLID;
552  max_space_p->max_space = -1;
553 
555 }
556 
557 static void
559 {
560  int rv;
562 
563  if (VPID_EQ (page_id_p, &catalog_Max_space.max_page_id))
564  {
565  catalog_Max_space.max_space = space;
566  }
567  else if (space > catalog_Max_space.max_space)
568  {
569  catalog_Max_space.max_page_id = *(page_id_p);
570  catalog_Max_space.max_space = space;
571  }
572 
574 }
575 
576 /*
577  * catalog_initialize_new_page () -
578  * return:
579  * vfid(in):
580  * file_type(in):
581  * vpid(in):
582  * ignore_npages(in):
583  * pg_ovfl(in):
584  */
585 /*
586  * catalog_initialize_new_page () - document me!
587  *
588  * return : Error code
589  * thread_p (in) : Thread entry
590  * page (in) : New catalog page
591  * args (in) : bool * (is_overflow_page)
592  */
593 static int
594 catalog_initialize_new_page (THREAD_ENTRY * thread_p, PAGE_PTR page, void *args)
595 {
596  CATALOG_PAGE_HEADER page_header;
597  PGSLOTID slot_id;
598  int success;
599  RECDES record = {
601  };
602  char data[CATALOG_PAGE_HEADER_SIZE + MAX_ALIGNMENT], *aligned_data;
603  bool is_overflow_page = *(bool *) args;
604 
605  aligned_data = PTR_ALIGN (data, MAX_ALIGNMENT);
606 
607  pgbuf_set_page_ptype (thread_p, page, PAGE_CATALOG);
609 
610  VPID_SET_NULL (&page_header.overflow_page_id);
611  page_header.dir_count = 0;
612  page_header.is_overflow_page = is_overflow_page;
613 
614  recdes_set_data_area (&record, aligned_data, CATALOG_PAGE_HEADER_SIZE);
615  catalog_put_page_header (record.data, &page_header);
616 
617  success = spage_insert (thread_p, page, &record, &slot_id);
618  if (success != SP_SUCCESS || slot_id != CATALOG_HEADER_SLOT)
619  {
620  assert (false);
621  if (success != SP_SUCCESS)
622  {
624  }
625  return ER_FAILED;
626  }
627 
628  log_append_undoredo_data2 (thread_p, RVCT_NEWPAGE, NULL, page, -1, 0, sizeof (CATALOG_PAGE_HEADER), NULL,
629  &page_header);
630 
631  pgbuf_set_dirty (thread_p, page, DONT_FREE);
632  return NO_ERROR;
633 }
634 
635 /*
636  * catalog_get_new_page () - Get a new page for the catalog
637  * return: The pointer to a newly allocated page, or NULL
638  * The parameter page_id is set to the page identifier.
639  * page_id(out): Set to the page identifier for the newly allocated page
640  * nearpg(in): A page identifier that may be used in a nearby page allocation.
641  * (It may be ignored.)
642  * pg_ovfl(in): Page is an overflow page (1) or not (0)
643  *
644  * Note: Allocates a new page for the catalog and inserts the header
645  * record for the page.
646  */
647 static PAGE_PTR
648 catalog_get_new_page (THREAD_ENTRY * thread_p, VPID * page_id_p, bool is_overflow_page)
649 {
650  PAGE_PTR page_p;
651 
652  log_sysop_start (thread_p);
653 
654  if (file_alloc (thread_p, &catalog_Id.vfid, catalog_initialize_new_page, &is_overflow_page, page_id_p, &page_p)
655  != NO_ERROR)
656  {
657  ASSERT_ERROR ();
658  log_sysop_abort (thread_p);
659  return NULL;
660  }
661  if (page_p == NULL)
662  {
663  assert_release (false);
664  log_sysop_abort (thread_p);
665  return NULL;
666  }
667  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
668  log_sysop_commit (thread_p);
669 
670  return page_p;
671 }
672 
673 /*
674  * catalog_file_map_find_optimal_page () - FILE_MAP_PAGE_FUNC function that checks a catalog page has enough space
675  * for a new record.
676  *
677  * return : error code
678  * thread_p (in) : thread entry
679  * page (in/out) : page to check. if page has enough space, its value is moved to context and the output of this pointer
680  * is NULL.
681  * stop (out) : output true if page has enough space
682  * args (in/out) : find optimal page context
683  */
684 static int
685 catalog_file_map_find_optimal_page (THREAD_ENTRY * thread_p, PAGE_PTR * page, bool * stop, void *args)
686 {
688  RECDES record;
689  int dir_count;
690 
691  (void) pgbuf_check_page_ptype (thread_p, *page, PAGE_CATALOG);
692 
693  if (spage_get_record (thread_p, *page, CATALOG_HEADER_SLOT, &record, PEEK) != S_SUCCESS)
694  {
695  assert_release (false);
696  return ER_FAILED;
697  }
699  {
700  /* overflow page */
701  return NO_ERROR;
702  }
704  dir_count = CATALOG_GET_PGHEADER_DIR_COUNT (record.data);
705  if (dir_count > 0)
706  {
707  context->size_optimal_free -= (int) (DB_PAGESIZE * (0.25f + (dir_count - 1) * 0.05f));
708  }
709  if (context->size_optimal_free > context->size)
710  {
711  /* found optimal page */
712  pgbuf_get_vpid (*page, &context->vpid_optimal);
713  context->page_optimal = *page;
714  *page = NULL;
715  *stop = true;
716  }
717  return NO_ERROR;
718 }
719 
720 /*
721  * catalog_find_optimal_page () -
722  * return: PAGE_PTR
723  * size(in): The size requested in the page
724  * page_id(out): Set to the page identifier fetched
725  */
726 static PAGE_PTR
727 catalog_find_optimal_page (THREAD_ENTRY * thread_p, int size, VPID * page_id_p)
728 {
729  PAGE_PTR page_p;
731 
732  assert (page_id_p != NULL);
733 
734  context.size = size;
735  VPID_SET_NULL (&context.vpid_optimal);
736  context.page_optimal = NULL;
737 
739 
740  if (catalog_Max_space.max_page_id.pageid != NULL_PAGEID && catalog_Max_space.max_space > size)
741  {
742  /* try to use page hint */
743  bool can_use = false;
744 
745  *page_id_p = catalog_Max_space.max_page_id;
747 
748  page_p = pgbuf_fix (thread_p, page_id_p, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
749  if (page_p == NULL)
750  {
751  ASSERT_ERROR ();
752  return NULL;
753  }
754  if (catalog_file_map_find_optimal_page (thread_p, &page_p, &can_use, &context) != NO_ERROR)
755  {
756  ASSERT_ERROR ();
757  return NULL;
758  }
759  if (can_use)
760  {
761  /* we can use cached page. careful, it was moved to context. */
762  assert (!VPID_ISNULL (&context.vpid_optimal));
763  assert (context.page_optimal != NULL);
764  assert (page_p == NULL);
765 
766  *page_id_p = context.vpid_optimal;
767  return context.page_optimal;
768  }
769  else
770  {
771  pgbuf_unfix_and_init (thread_p, page_p);
772  }
773 
774  /* need another page */
776  }
777 
778  /* todo: search the file table for enough empty space. this system is not ideal at all! but we have no other means
779  * of reusing free space. we'll need a different design for catalog file or a free space map or anything.
780  * maybe we'll consider catalog when we'll rethink the best space system of heap file.
781  */
782 
783  if (file_map_pages (thread_p, &catalog_Id.vfid, PGBUF_LATCH_WRITE, PGBUF_CONDITIONAL_LATCH,
785  {
786  ASSERT_ERROR ();
788  return NULL;
789  }
790 
791  if (context.page_optimal != NULL)
792  {
793  if (catalog_Max_space.max_page_id.pageid == NULL_PAGEID
794  || catalog_Max_space.max_space < context.size_optimal_free - size)
795  {
796  /* replace entry in max space */
797  catalog_Max_space.max_page_id = context.vpid_optimal;
798  catalog_Max_space.max_space = context.size_optimal_free;
799  }
800 
802 
803  *page_id_p = context.vpid_optimal;
804  return context.page_optimal;
805  }
806 
807  /* no page with enough space was found */
808  page_p = catalog_get_new_page (thread_p, page_id_p, false);
809  if (page_p == NULL)
810  {
811  ASSERT_ERROR ();
813  return NULL;
814  }
815 
816  catalog_Max_space.max_page_id = *page_id_p;
817  catalog_Max_space.max_space = spage_max_space_for_new_record (thread_p, page_p) - CATALOG_MAX_SLOT_ID_SIZE;
819 
820  return page_p;
821 }
822 
823 /*
824  * catalog_free_representation () - Free disk representation memory area
825  * return: nothing
826  * dr(in): Disk representation structure pointer
827  */
828 void
830 {
831  int attr_cnt, k, j;
832  DISK_ATTR *attr_p;
833  BTREE_STATS *stat_p;
834 
835  if (repr_p != NULL)
836  {
837  attr_cnt = repr_p->n_fixed + repr_p->n_variable;
838  for (k = 0; k < attr_cnt; k++)
839  {
840  attr_p = ((k < repr_p->n_fixed)
841  ? (DISK_ATTR *) repr_p->fixed + k : (DISK_ATTR *) repr_p->variable + (k - repr_p->n_fixed));
842 
843  if (attr_p->value != NULL)
844  {
846  }
847 
848  if (attr_p->bt_stats != NULL)
849  {
850  for (j = 0; j < attr_p->n_btstats; j++)
851  {
852  stat_p = &(attr_p->bt_stats[j]);
853  if (stat_p->pkeys != NULL)
854  {
856  }
857  }
859  }
860  }
861 
862  if (repr_p->fixed != NULL)
863  {
865  }
866 
867  if (repr_p->variable != NULL)
868  {
870  }
871 
872  db_private_free_and_init (NULL, repr_p);
873  }
874 }
875 
876 /*
877  * catalog_free_class_info () - Free class specific information memory area
878  * return: nothing
879  * cls_info(in): Pointer to the class information structure
880  */
881 void
883 {
884  if (class_info_p)
885  {
886  db_private_free_and_init (NULL, class_info_p);
887  }
888 }
889 
890 /*
891  * catalog_get_key_list () -
892  * return: NO_ERROR or error code
893  * key(in):
894  * val(in):
895  * args(in):
896  */
897 static int
898 catalog_get_key_list (THREAD_ENTRY * thread_p, void *key, void *ignore_value, void *args)
899 {
900  CATALOG_CLASS_ID_LIST *class_id_p, **p;
901 
902  p = (CATALOG_CLASS_ID_LIST **) args;
903 
904  class_id_p = (CATALOG_CLASS_ID_LIST *) db_private_alloc (thread_p, sizeof (CATALOG_CLASS_ID_LIST));
905 
906  if (class_id_p == NULL)
907  {
909  }
910 
911  class_id_p->class_id.volid = ((OID *) key)->volid;
912  class_id_p->class_id.pageid = ((OID *) key)->pageid;
913  class_id_p->class_id.slotid = ((OID *) key)->slotid;
914  class_id_p->next = *p;
915 
916  *p = class_id_p;
917 
918  return NO_ERROR;
919 }
920 
921 /*
922  * catalog_free_key_list () -
923  * return:
924  * clsid_list(in):
925  */
926 static void
928 {
929  CATALOG_CLASS_ID_LIST *p, *next;
930 
931  if (class_id_list == NULL)
932  {
933  return;
934  }
935 
936  for (p = class_id_list; p; p = next)
937  {
938  next = p->next;
940  }
941 
942  class_id_list = NULL;
943 }
944 
945 /*
946  * catalog_entry_alloc () - allocate a catalog entry
947  * returns: new pointer or NULL on error
948  */
949 static void *
951 {
952  return malloc (sizeof (CATALOG_ENTRY));
953 }
954 
955 /*
956  * catalog_entry_free () - free a catalog entry
957  * returns: error code or NO_ERROR
958  * ent(in): entry to free
959  */
960 static int
962 {
963  free (ent);
964  return NO_ERROR;
965 }
966 
967 /*
968  * catalog_entry_init () - initialize a catalog entry
969  * returns: error code or NO_ERROR
970  * ent(in): entry to initialize
971  */
972 static int
974 {
975  /* TO BE FILLED IN IF NECESSARY */
976  return NO_ERROR;
977 }
978 
979 /*
980  * catalog_entry_uninit () - uninitialize a catalog entry
981  * returns: error code or NO_ERROR
982  * ent(in): entry to uninitialize
983  */
984 static int
986 {
987  /* TO BE FILLED IN IF NECESSARY */
988  return NO_ERROR;
989 }
990 
991 /*
992  * catalog_key_copy () - copy a key
993  * returns: error code or NO_ERROR
994  * src(in): source key
995  * dest(in): destination key
996  */
997 static int
998 catalog_key_copy (void *src, void *dest)
999 {
1000  CATALOG_KEY *src_k = (CATALOG_KEY *) src;
1001  CATALOG_KEY *dest_k = (CATALOG_KEY *) dest;
1002 
1003  if (src_k == NULL || dest_k == NULL)
1004  {
1005  return ER_FAILED;
1006  }
1007 
1008  /* copy key members */
1009  dest_k->page_id = src_k->page_id;
1010  dest_k->repr_id = src_k->repr_id;
1011  dest_k->slot_id = src_k->slot_id;
1012  dest_k->volid = src_k->volid;
1013 
1014  /* copy data members */
1015  VPID_COPY (&dest_k->r_page_id, &src_k->r_page_id);
1016  dest_k->r_slot_id = src_k->r_slot_id;
1017 
1018  return NO_ERROR;
1019 }
1020 
1021 /*
1022  * catalog_compare () - Compare two catalog keys
1023  * return: int (true or false)
1024  * key1(in): First catalog key
1025  * key2(in): Second catalog key
1026  */
1027 static int
1028 catalog_key_compare (void *key1, void *key2)
1029 {
1030  const CATALOG_KEY *k1, *k2;
1031 
1032  k1 = (const CATALOG_KEY *) key1;
1033  k2 = (const CATALOG_KEY *) key2;
1034 
1035  /* only compare key members */
1036  if (k1->page_id == k2->page_id && k1->slot_id == k2->slot_id && k1->repr_id == k2->repr_id && k1->volid == k2->volid)
1037  {
1038  /* equal */
1039  return 0;
1040  }
1041  else
1042  {
1043  /* not equal */
1044  return 1;
1045  }
1046 }
1047 
1048 /*
1049  * catalog_hash () -
1050  * return: int
1051  * key(in): Catalog key
1052  * htsize(in): Memory Hash Table Size
1053  *
1054  * Note: Generate a hash number for the given key for the given hash table size.
1055  */
1056 static unsigned int
1057 catalog_key_hash (void *key, int hash_table_size)
1058 {
1059  const CATALOG_KEY *k1 = (const CATALOG_KEY *) key;
1060  unsigned int hash_res;
1061 
1062  hash_res =
1063  ((((k1)->slot_id | ((k1)->page_id << 8)) ^ (((k1)->page_id >> 8) | (((PAGEID) (k1)->volid) << 24))) + k1->repr_id);
1064 
1065  return (hash_res % hash_table_size);
1066 }
1067 
1068 /*
1069  * catalog_put_record_into_page () -
1070  * return: NO_ERROR or ER_FAILED
1071  * ct_recordp(in): pointer to CATALOG_RECORD structure
1072  * next(in): flag of next page
1073  * remembered_slotid(in):
1074  *
1075  * Note: Put the catalog record into the page and then prepare next page.
1076  */
1077 static int
1078 catalog_put_record_into_page (THREAD_ENTRY * thread_p, CATALOG_RECORD * catalog_record_p, int next,
1079  PGSLOTID * remembered_slot_id_p)
1080 {
1081  PAGE_PTR new_page_p;
1082  VPID new_vpid;
1083 
1084  /* if some space in 'recdes'data' is remained */
1085  if (catalog_record_p->offset < catalog_record_p->recdes.area_size)
1086  {
1087  return NO_ERROR;
1088  }
1089 
1090  if (spage_insert (thread_p, catalog_record_p->page_p, &catalog_record_p->recdes, &catalog_record_p->slotid) !=
1091  SP_SUCCESS)
1092  {
1093  pgbuf_unfix_and_init (thread_p, catalog_record_p->page_p);
1094  return ER_FAILED;
1095  }
1096 
1097  if (*remembered_slot_id_p == NULL_SLOTID)
1098  {
1099  *remembered_slot_id_p = catalog_record_p->slotid;
1100  }
1101 
1102  log_append_undoredo_recdes2 (thread_p, RVCT_INSERT, &catalog_Id.vfid, catalog_record_p->page_p,
1103  catalog_record_p->slotid, NULL, &catalog_record_p->recdes);
1104  pgbuf_set_dirty (thread_p, catalog_record_p->page_p, DONT_FREE);
1105 
1106  /* if there's no need to get next page; when this is the last page */
1107  if (!next)
1108  {
1109  catalog_record_p->slotid = *remembered_slot_id_p;
1110  *remembered_slot_id_p = NULL_SLOTID;
1111  return NO_ERROR;
1112  }
1113 
1114  new_page_p = catalog_get_new_page (thread_p, &new_vpid, true);
1115  if (new_page_p == NULL)
1116  {
1117  pgbuf_unfix_and_init (thread_p, catalog_record_p->page_p);
1118  return ER_FAILED;
1119  }
1120 
1121  log_append_undo_data2 (thread_p, RVCT_NEW_OVFPAGE_LOGICAL_UNDO, &catalog_Id.vfid, NULL, -1, sizeof (new_vpid),
1122  &new_vpid);
1123 
1124  /* make the previous page point to the newly allocated page */
1125  catalog_record_p->recdes.area_size = DB_PAGESIZE;
1126  (void) spage_get_record (thread_p, catalog_record_p->page_p, CATALOG_HEADER_SLOT, &catalog_record_p->recdes, COPY);
1127 
1128  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, catalog_record_p->page_p, CATALOG_HEADER_SLOT,
1129  &catalog_record_p->recdes);
1130 
1131  CATALOG_PUT_PGHEADER_OVFL_PGID_PAGEID (catalog_record_p->recdes.data, new_vpid.pageid);
1132  CATALOG_PUT_PGHEADER_OVFL_PGID_VOLID (catalog_record_p->recdes.data, new_vpid.volid);
1133 
1134  if (spage_update (thread_p, catalog_record_p->page_p, CATALOG_HEADER_SLOT, &catalog_record_p->recdes) != SP_SUCCESS)
1135  {
1136  pgbuf_unfix_and_init (thread_p, catalog_record_p->page_p);
1137  return ER_FAILED;
1138  }
1139 
1140  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, catalog_record_p->page_p, CATALOG_HEADER_SLOT,
1141  &catalog_record_p->recdes);
1142 
1143  pgbuf_set_dirty (thread_p, catalog_record_p->page_p, FREE);
1144 
1145  catalog_record_p->vpid.pageid = new_vpid.pageid;
1146  catalog_record_p->vpid.volid = new_vpid.volid;
1147  catalog_record_p->page_p = new_page_p;
1148  catalog_record_p->recdes.area_size = spage_max_space_for_new_record (thread_p, new_page_p) - CATALOG_MAX_SLOT_ID_SIZE;
1149  catalog_record_p->recdes.length = 0;
1150  catalog_record_p->offset = 0;
1151 
1152  return NO_ERROR;
1153 }
1154 
1155 static int
1157  PGSLOTID * remembered_slot_id_p, int format_size)
1158 {
1159  /* if the remained, unwritten portion of the record data is smaller than the size of disk format of structure */
1160  if (catalog_record_p->recdes.area_size - catalog_record_p->offset < format_size)
1161  {
1162  /* set the record length as the current offset, the size of written portion of the record data, and set the
1163  * offset to the end of the record data to write the page */
1164  catalog_record_p->recdes.length = catalog_record_p->offset;
1165  catalog_record_p->offset = catalog_record_p->recdes.area_size;
1166 
1167  if (catalog_put_record_into_page (thread_p, catalog_record_p, 1, remembered_slot_id_p) != NO_ERROR)
1168  {
1169  return ER_FAILED;
1170  }
1171  }
1172 
1173  return NO_ERROR;
1174 }
1175 
1176 /*
1177  * catalog_store_disk_representation () -
1178  * return: NO_ERROR or ER_FAILED
1179  * disk_reprp(in): pointer to DISK_REPR structure (disk representation)
1180  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1181  * remembered_slotid(in):
1182  *
1183  * Note: Transforms disk representation form into catalog disk form.
1184  * Store DISK_REPR structure into catalog record.
1185  */
1186 static int
1187 catalog_store_disk_representation (THREAD_ENTRY * thread_p, DISK_REPR * disk_repr_p, CATALOG_RECORD * catalog_record_p,
1188  PGSLOTID * remembered_slot_id_p)
1189 {
1190  if (catalog_write_unwritten_portion (thread_p, catalog_record_p, remembered_slot_id_p, CATALOG_DISK_REPR_SIZE) !=
1191  NO_ERROR)
1192  {
1193  return ER_FAILED;
1194  }
1195 
1196  catalog_put_disk_representation (catalog_record_p->recdes.data + catalog_record_p->offset, disk_repr_p);
1197  catalog_record_p->offset += CATALOG_DISK_REPR_SIZE;
1198 
1199  return NO_ERROR;
1200 }
1201 
1202 /*
1203  * catalog_store_disk_attribute () -
1204  * NO_ERROR or ER_FAILED
1205  * disk_attrp(in): pointer to DISK_ATTR structure (disk representation)
1206  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1207  * remembered_slotid(in):
1208  *
1209  * Note: Transforms disk representation form into catalog disk form.
1210  * Store DISK_ATTR structure into catalog record.
1211  */
1212 static int
1213 catalog_store_disk_attribute (THREAD_ENTRY * thread_p, DISK_ATTR * disk_attr_p, CATALOG_RECORD * catalog_record_p,
1214  PGSLOTID * remembered_slot_id_p)
1215 {
1216  if (catalog_write_unwritten_portion (thread_p, catalog_record_p, remembered_slot_id_p, CATALOG_DISK_ATTR_SIZE) !=
1217  NO_ERROR)
1218  {
1219  return ER_FAILED;
1220  }
1221 
1222  catalog_put_disk_attribute (catalog_record_p->recdes.data + catalog_record_p->offset, disk_attr_p);
1223  catalog_record_p->offset += CATALOG_DISK_ATTR_SIZE;
1224 
1225  return NO_ERROR;
1226 }
1227 
1228 /*
1229  * catalog_store_attribute_value () -
1230  * return: NO_ERROR or ER_FAILED
1231  * value(in): pointer to the value data (disk representation)
1232  * length(in): length of the value data
1233  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1234  * remembered_slotid(in):
1235  *
1236  * Note: Transforms disk representation form into catalog disk form.
1237  * Store value data into catalog record.
1238  */
1239 static int
1240 catalog_store_attribute_value (THREAD_ENTRY * thread_p, void *value, int length, CATALOG_RECORD * catalog_record_p,
1241  PGSLOTID * remembered_slot_id_p)
1242 {
1243  int offset = 0;
1244  int bufsize;
1245 
1246  if (catalog_write_unwritten_portion (thread_p, catalog_record_p, remembered_slot_id_p, length) != NO_ERROR)
1247  {
1248  return ER_FAILED;
1249  }
1250 
1251  while (offset < length)
1252  {
1253  if (length - offset <= catalog_record_p->recdes.area_size - catalog_record_p->offset)
1254  {
1255  /* if the size of the value is smaller than or equals to the remaining size of the recdes.data, just copy the
1256  * value into the recdes.data buffer and adjust the offset. */
1257  bufsize = length - offset;
1258  (void) memcpy (catalog_record_p->recdes.data + catalog_record_p->offset, (char *) value + offset, bufsize);
1259  catalog_record_p->offset += bufsize;
1260  break;
1261  }
1262  else
1263  {
1264  /* if the size of the value is larger than the whole size of the recdes.data, we need split the value over N
1265  * pages. The first N-1 pages need to be stored into pages, while the last page can be stored in the
1266  * recdes.data buffer as the existing routine. */
1267  assert (catalog_record_p->offset == 0);
1268  bufsize = catalog_record_p->recdes.area_size;
1269  (void) memcpy (catalog_record_p->recdes.data, (char *) value + offset, bufsize);
1270  offset += bufsize;
1271 
1272  /* write recdes.data and fill catalog_record_p as new page */
1273  catalog_record_p->offset = catalog_record_p->recdes.area_size;
1274  catalog_record_p->recdes.length = catalog_record_p->offset;
1275  if (catalog_put_record_into_page (thread_p, catalog_record_p, 1, remembered_slot_id_p) != NO_ERROR)
1276  {
1277  return ER_FAILED;
1278  }
1279  }
1280  }
1281  return NO_ERROR;
1282 }
1283 
1284 /*
1285  * catalog_store_btree_statistics () -
1286  * return: NO_ERROR or ER_FAILED
1287  * bt_statsp(in): pointer to BTREE_STATS structure (disk representation)
1288  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1289  * remembered_slotid(in):
1290  *
1291  * Note: Transforms disk representation form into catalog disk form.
1292  * Store BTREE_STATS structure into catalog record.
1293  */
1294 static int
1295 catalog_store_btree_statistics (THREAD_ENTRY * thread_p, BTREE_STATS * btree_stats_p, CATALOG_RECORD * catalog_record_p,
1296  PGSLOTID * remembered_slot_id_p)
1297 {
1298  if (catalog_write_unwritten_portion (thread_p, catalog_record_p, remembered_slot_id_p, CATALOG_BT_STATS_SIZE) !=
1299  NO_ERROR)
1300  {
1301  return ER_FAILED;
1302  }
1303 
1304  catalog_put_btree_statistics (catalog_record_p->recdes.data + catalog_record_p->offset, btree_stats_p);
1305  catalog_record_p->offset += CATALOG_BT_STATS_SIZE;
1306 
1307  return NO_ERROR;
1308 }
1309 
1310 /*
1311  * catalog_get_record_from_page () - Get the catalog record from the page.
1312  * return: NO_ERROR or ER_FAILED
1313  * ct_recordp(in): pointer to CATALOG_RECORD structure
1314  */
1315 static int
1317 {
1318  /* if some data in 'recdes.data' is remained */
1319  if (catalog_record_p->offset < catalog_record_p->recdes.length)
1320  {
1321  return NO_ERROR;
1322  }
1323 
1324  /* if it is not first time, if there was the page previously read */
1325  if (catalog_record_p->page_p)
1326  {
1327  if (spage_get_record (thread_p, catalog_record_p->page_p, CATALOG_HEADER_SLOT, &catalog_record_p->recdes, PEEK) !=
1328  S_SUCCESS)
1329  {
1330  return ER_FAILED;
1331  }
1332 
1333  catalog_record_p->vpid.pageid = CATALOG_GET_PGHEADER_OVFL_PGID_PAGEID (catalog_record_p->recdes.data);
1334  catalog_record_p->vpid.volid = CATALOG_GET_PGHEADER_OVFL_PGID_VOLID (catalog_record_p->recdes.data);
1335  catalog_record_p->slotid = 1;
1336 
1337  pgbuf_unfix_and_init (thread_p, catalog_record_p->page_p);
1338  }
1339 
1340  if (catalog_record_p->vpid.pageid == NULL_PAGEID || catalog_record_p->vpid.volid == NULL_VOLID)
1341  {
1342  return ER_FAILED;
1343  }
1344 
1345  catalog_record_p->page_p =
1346  pgbuf_fix (thread_p, &catalog_record_p->vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
1347  if (catalog_record_p->page_p == NULL)
1348  {
1349  return ER_FAILED;
1350  }
1351 
1352  (void) pgbuf_check_page_ptype (thread_p, catalog_record_p->page_p, PAGE_CATALOG);
1353 
1354  if (spage_get_record (thread_p, catalog_record_p->page_p, catalog_record_p->slotid, &catalog_record_p->recdes, PEEK)
1355  != S_SUCCESS)
1356  {
1357  pgbuf_unfix_and_init (thread_p, catalog_record_p->page_p);
1358  return ER_FAILED;
1359  }
1360 
1361  catalog_record_p->offset = 0;
1362  return NO_ERROR;
1363 }
1364 
1365 static int
1366 catalog_read_unread_portion (THREAD_ENTRY * thread_p, CATALOG_RECORD * catalog_record_p, int format_size)
1367 {
1368  if (catalog_record_p->recdes.length - catalog_record_p->offset < format_size)
1369  {
1370  catalog_record_p->offset = catalog_record_p->recdes.length;
1371  if (catalog_get_record_from_page (thread_p, catalog_record_p) != NO_ERROR)
1372  {
1373  return ER_FAILED;
1374  }
1375  }
1376 
1377  return NO_ERROR;
1378 }
1379 
1380 /*
1381  * catalog_fetch_disk_representation () -
1382  * return: NO_ERROR or ER_FAILED
1383  * disk_reprp(in): pointer to DISK_REPR structure (disk representation)
1384  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1385  *
1386  * Note: Transforms catalog disk form into disk representation form.
1387  * Fetch DISK_REPR structure from catalog record.
1388  */
1389 static int
1390 catalog_fetch_disk_representation (THREAD_ENTRY * thread_p, DISK_REPR * disk_repr_p, CATALOG_RECORD * catalog_record_p)
1391 {
1392  if (catalog_read_unread_portion (thread_p, catalog_record_p, CATALOG_DISK_REPR_SIZE) != NO_ERROR)
1393  {
1394  return ER_FAILED;
1395  }
1396 
1397  catalog_get_disk_representation (disk_repr_p, catalog_record_p->recdes.data + catalog_record_p->offset);
1398  catalog_record_p->offset += CATALOG_DISK_REPR_SIZE;
1399 
1400  return NO_ERROR;
1401 }
1402 
1403 /*
1404  * catalog_fetch_disk_attribute () -
1405  * return: NO_ERROR or ER_FAILED
1406  * disk_attrp(in): pointer to DISK_ATTR structure (disk representation)
1407  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1408  *
1409  * Note: Transforms catalog disk form into disk representation form.
1410  * Fetch DISK_ATTR structure from catalog record.
1411  */
1412 static int
1413 catalog_fetch_disk_attribute (THREAD_ENTRY * thread_p, DISK_ATTR * disk_attr_p, CATALOG_RECORD * catalog_record_p)
1414 {
1415  if (catalog_read_unread_portion (thread_p, catalog_record_p, CATALOG_DISK_ATTR_SIZE) != NO_ERROR)
1416  {
1417  return ER_FAILED;
1418  }
1419 
1420  catalog_get_disk_attribute (disk_attr_p, catalog_record_p->recdes.data + catalog_record_p->offset);
1421  catalog_record_p->offset += CATALOG_DISK_ATTR_SIZE;
1422 
1423  return NO_ERROR;
1424 }
1425 
1426 /*
1427  * catalog_fetch_attribute_value () -
1428  * return: NO_ERROR or ER_FAILED
1429  * value(in): pointer to the value data (disk representation)
1430  * length(in): length of the value data
1431  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1432  *
1433  * Note: Transforms catalog disk form into disk representation form.
1434  * Fetch value data from catalog record.
1435  */
1436 static int
1437 catalog_fetch_attribute_value (THREAD_ENTRY * thread_p, void *value, int length, CATALOG_RECORD * catalog_record_p)
1438 {
1439  int offset = 0;
1440  int bufsize;
1441 
1442  if (catalog_read_unread_portion (thread_p, catalog_record_p, length) != NO_ERROR)
1443  {
1444  return ER_FAILED;
1445  }
1446 
1447  while (offset < length)
1448  {
1449  if (length - offset <= catalog_record_p->recdes.length - catalog_record_p->offset)
1450  {
1451  /* if the size of the value is smaller than or equals to the remaining length of the recdes.data, just read
1452  * the value from the recdes.data buffer and adjust the offset. */
1453  bufsize = length - offset;
1454  (void) memcpy ((char *) value + offset, catalog_record_p->recdes.data + catalog_record_p->offset, bufsize);
1455  catalog_record_p->offset += bufsize;
1456  break;
1457  }
1458  else
1459  {
1460  /* if the size of the value is larger than the whole length of the recdes.data, that means the value has been
1461  * stored in N pages, we need to fetch these N pages and read value from them. in first N-1 page, the whole
1462  * page will be read into the value buffer, while in last page, the remaining value will be read into value
1463  * buffer as the existing routine. */
1464  assert (catalog_record_p->offset == 0);
1465  bufsize = catalog_record_p->recdes.length;
1466  (void) memcpy ((char *) value + offset, catalog_record_p->recdes.data, bufsize);
1467  offset += bufsize;
1468 
1469  /* read next page and fill the catalog_record_p */
1470  catalog_record_p->offset = catalog_record_p->recdes.length;
1471  if (catalog_get_record_from_page (thread_p, catalog_record_p) != NO_ERROR)
1472  {
1473  return ER_FAILED;
1474  }
1475  }
1476  }
1477 
1478  return NO_ERROR;
1479 }
1480 
1481 /*
1482  * catalog_fetch_btree_statistics () -
1483  * return: NO_ERROR or ER_FAILED
1484  * bt_statsp(in): pointer to BTREE_STATS structure (disk representation)
1485  * ct_recordp(in): pointer to CATALOG_RECORD structure (catalog record)
1486  *
1487  * Note: Transforms catalog disk form into disk representation form.
1488  * Fetch BTREE_STATS structure from catalog record.
1489  */
1490 static int
1491 catalog_fetch_btree_statistics (THREAD_ENTRY * thread_p, BTREE_STATS * btree_stats_p, CATALOG_RECORD * catalog_record_p)
1492 {
1493  VPID root_vpid;
1494  PAGE_PTR root_page_p;
1495  BTREE_ROOT_HEADER *root_header = NULL;
1496  int i;
1497  OR_BUF buf;
1498 
1499  if (catalog_read_unread_portion (thread_p, catalog_record_p, CATALOG_BT_STATS_SIZE) != NO_ERROR)
1500  {
1501  return ER_FAILED;
1502  }
1503 
1504  btree_stats_p->leafs = 0;
1505  btree_stats_p->pages = 0;
1506  btree_stats_p->height = 0;
1507  btree_stats_p->keys = 0;
1508  btree_stats_p->pkeys_size = 0;
1509  btree_stats_p->pkeys = NULL;
1510 
1511  CATALOG_GET_BT_STATS_BTID (&btree_stats_p->btid, catalog_record_p->recdes.data + catalog_record_p->offset);
1512 
1513  root_vpid.pageid = btree_stats_p->btid.root_pageid;
1514  root_vpid.volid = btree_stats_p->btid.vfid.volid;
1515  if (VPID_ISNULL (&root_vpid))
1516  {
1517  /* after create the catalog record of the class, and before create the catalog record of the constraints for the
1518  * class currently, does not know BTID */
1519  btree_stats_p->key_type = &tp_Null_domain;
1520  goto exit_on_end;
1521  }
1522 
1523  root_page_p = pgbuf_fix (thread_p, &root_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
1524  if (root_page_p == NULL)
1525  {
1526  return ER_FAILED;
1527  }
1528 
1529  (void) pgbuf_check_page_ptype (thread_p, root_page_p, PAGE_BTREE);
1530 
1531  root_header = btree_get_root_header (thread_p, root_page_p);
1532  if (root_header == NULL)
1533  {
1534  pgbuf_unfix_and_init (thread_p, root_page_p);
1535  return ER_FAILED;
1536  }
1537 
1538  or_init (&buf, root_header->packed_key_domain, -1);
1539  btree_stats_p->key_type = or_get_domain (&buf, NULL, NULL);
1540 
1541  pgbuf_unfix_and_init (thread_p, root_page_p);
1542 
1543  if (TP_DOMAIN_TYPE (btree_stats_p->key_type) == DB_TYPE_MIDXKEY)
1544  {
1545  btree_stats_p->pkeys_size = tp_domain_size (btree_stats_p->key_type->setdomain);
1546  }
1547  else
1548  {
1549  btree_stats_p->pkeys_size = 1;
1550  }
1551 
1552  /* cut-off to stats */
1553  if (btree_stats_p->pkeys_size > BTREE_STATS_PKEYS_NUM)
1554  {
1555  btree_stats_p->pkeys_size = BTREE_STATS_PKEYS_NUM;
1556  }
1557 
1558  btree_stats_p->pkeys = (int *) db_private_alloc (thread_p, btree_stats_p->pkeys_size * sizeof (int));
1559  if (btree_stats_p->pkeys == NULL)
1560  {
1561  return ER_FAILED;
1562  }
1563 
1564  assert (btree_stats_p->pkeys_size <= BTREE_STATS_PKEYS_NUM);
1565  for (i = 0; i < btree_stats_p->pkeys_size; i++)
1566  {
1567  btree_stats_p->pkeys[i] = 0;
1568  }
1569 
1570 exit_on_end:
1571 
1572  catalog_get_btree_statistics (btree_stats_p, catalog_record_p->recdes.data + catalog_record_p->offset);
1573  catalog_record_p->offset += CATALOG_BT_STATS_SIZE;
1574 
1575  return NO_ERROR;
1576 }
1577 
1578 static int
1579 catalog_drop_representation_helper (THREAD_ENTRY * thread_p, PAGE_PTR page_p, VPID * page_id_p, PGSLOTID slot_id)
1580 {
1581  PAGE_PTR overflow_page_p;
1582  VPID overflow_vpid, new_overflow_vpid;
1583  PGLENGTH new_space;
1584  RECDES record = { 0, -1, REC_HOME, NULL };
1585  int error_code;
1586 
1587  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
1588 
1590  {
1591  return ER_FAILED;
1592  }
1593 
1594  if (spage_get_record (thread_p, page_p, slot_id, &record, COPY) != S_SUCCESS)
1595  {
1596  recdes_free_data_area (&record);
1597  if (er_errid () == ER_SP_UNKNOWN_SLOTID)
1598  {
1599  return NO_ERROR;
1600  }
1601  return ER_FAILED;
1602  }
1603 
1604  log_append_undoredo_recdes2 (thread_p, RVCT_DELETE, &catalog_Id.vfid, page_p, slot_id, &record, NULL);
1605 
1606  if (spage_delete (thread_p, page_p, slot_id) != slot_id)
1607  {
1608  recdes_free_data_area (&record);
1609  return ER_FAILED;
1610  }
1611 
1612  new_space = spage_max_space_for_new_record (thread_p, page_p);
1613  catalog_update_max_space (page_id_p, new_space);
1614 
1615  spage_get_record (thread_p, page_p, CATALOG_HEADER_SLOT, &record, COPY);
1616 
1617  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, CATALOG_HEADER_SLOT, &record);
1618 
1619  overflow_vpid.pageid = CATALOG_GET_PGHEADER_OVFL_PGID_PAGEID (record.data);
1620  overflow_vpid.volid = CATALOG_GET_PGHEADER_OVFL_PGID_VOLID (record.data);
1621 
1622  if (overflow_vpid.pageid != NULL_PAGEID)
1623  {
1626 
1627  if (spage_update (thread_p, page_p, CATALOG_HEADER_SLOT, &record) != SP_SUCCESS)
1628  {
1629  recdes_free_data_area (&record);
1630  return ER_FAILED;
1631  }
1632 
1633  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, CATALOG_HEADER_SLOT, &record);
1634  }
1635 
1636  recdes_free_data_area (&record);
1637 
1638  while (overflow_vpid.pageid != NULL_PAGEID)
1639  {
1640  /* delete the records in the overflow pages, if any */
1641  overflow_page_p = pgbuf_fix (thread_p, &overflow_vpid, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
1642  if (overflow_page_p == NULL)
1643  {
1644  return ER_FAILED;
1645  }
1646 
1647  (void) pgbuf_check_page_ptype (thread_p, overflow_page_p, PAGE_CATALOG);
1648 
1649  spage_get_record (thread_p, overflow_page_p, CATALOG_HEADER_SLOT, &record, PEEK);
1650  new_overflow_vpid.pageid = CATALOG_GET_PGHEADER_OVFL_PGID_PAGEID (record.data);
1651  new_overflow_vpid.volid = CATALOG_GET_PGHEADER_OVFL_PGID_VOLID (record.data);
1652 
1653  pgbuf_unfix_and_init (thread_p, overflow_page_p);
1654 
1655  error_code = file_dealloc (thread_p, &catalog_Id.vfid, &overflow_vpid, FILE_CATALOG);
1656  if (error_code != NO_ERROR)
1657  {
1658  ASSERT_ERROR ();
1659  return error_code;
1660  }
1661  overflow_vpid = new_overflow_vpid;
1662  }
1663 
1664  return NO_ERROR;
1665 }
1666 
1667 /*
1668  * catalog_drop_disk_representation_from_page () -
1669  * return: NO_ERROR or ER_FAILED
1670  * page_id(in): Page identifier for the catalog unit
1671  * slot_id(in): Slot identifier for the catalog unit
1672  *
1673  * Note: The catalog storage unit whose location is identified with
1674  * the given page and slot identifier is deleted from the
1675  * catalog page. If there overflow pages pointed by the given
1676  * catalog unit, the overflow pages are deallocated.
1677  */
1678 static int
1680 {
1681  PAGE_PTR page_p;
1682 
1683  page_p = pgbuf_fix (thread_p, page_id_p, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
1684  if (page_p == NULL)
1685  {
1686  return ER_FAILED;
1687  }
1688 
1689  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
1690 
1691  if (catalog_drop_representation_helper (thread_p, page_p, page_id_p, slot_id) != NO_ERROR)
1692  {
1693  pgbuf_unfix_and_init (thread_p, page_p);
1694  return ER_FAILED;
1695  }
1696 
1697  pgbuf_set_dirty (thread_p, page_p, FREE);
1698  return NO_ERROR;
1699 }
1700 
1701 /*
1702  * catalog_drop_representation_class_from_page () -
1703  * return: NO_ERROR or ER_FAILED
1704  * dir_pgid(in): Directory page identifier
1705  * dir_pgptr(in/out): Directory page pointer
1706  * page_id(in): Catalog unit page identifier
1707  * slot_id(in): Catalog unit slot identifier
1708  *
1709  * Note: The catalog storage unit which can be disk representation or
1710  * class information record, whose location is identified by the
1711  * given page and slot identifier is deleted from the catalog page.
1712  */
1713 static int
1714 catalog_drop_representation_class_from_page (THREAD_ENTRY * thread_p, VPID * dir_page_id_p, PAGE_PTR * dir_page_p,
1715  VPID * page_id_p, PGSLOTID slot_id)
1716 {
1717  PAGE_PTR page_p = NULL;
1718  bool same_page;
1719 
1720  assert (dir_page_p != NULL && (*dir_page_p) != NULL);
1721  /* directory and repr. to be deleted are on the same page? */
1722  same_page = VPID_EQ (page_id_p, dir_page_id_p) ? true : false;
1723 
1724  if (same_page)
1725  {
1726  page_p = *dir_page_p;
1727  }
1728  else
1729  {
1730  int again_count = 0;
1731  int again_max = 20;
1732 
1733  try_again:
1734  /* avoid page deadlock */
1735  page_p = pgbuf_fix (thread_p, page_id_p, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_CONDITIONAL_LATCH);
1736  if (page_p == NULL)
1737  {
1738  /* try reverse order */
1739  pgbuf_unfix_and_init (thread_p, *dir_page_p);
1740 
1741  page_p = pgbuf_fix (thread_p, page_id_p, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
1742  if (page_p == NULL)
1743  {
1744  return ER_FAILED;
1745  }
1746 
1747  *dir_page_p = pgbuf_fix (thread_p, dir_page_id_p, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_CONDITIONAL_LATCH);
1748  if ((*dir_page_p) == NULL)
1749  {
1750  pgbuf_unfix_and_init (thread_p, page_p);
1751 
1752  *dir_page_p = pgbuf_fix (thread_p, dir_page_id_p, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
1753  if ((*dir_page_p) == NULL)
1754  {
1755  return ER_FAILED;
1756  }
1757 
1758  if (again_count++ >= again_max)
1759  {
1760  if (er_errid () == NO_ERROR)
1761  {
1763  page_id_p->pageid);
1764  }
1765 
1766  return ER_FAILED;
1767  }
1768  else
1769  {
1770  goto try_again;
1771  }
1772  }
1773  }
1774 
1775  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
1776  }
1777 
1778  if (catalog_drop_representation_helper (thread_p, page_p, page_id_p, slot_id) != NO_ERROR)
1779  {
1780  if (!same_page)
1781  {
1782  pgbuf_unfix_and_init (thread_p, page_p);
1783  }
1784  return ER_FAILED;
1785  }
1786 
1787  if (same_page)
1788  {
1789  pgbuf_set_dirty (thread_p, page_p, DONT_FREE);
1790  }
1791  else
1792  {
1793  pgbuf_set_dirty (thread_p, page_p, FREE);
1794  }
1795 
1796  return NO_ERROR;
1797 }
1798 
1799 static int
1800 catalog_get_rep_dir (THREAD_ENTRY * thread_p, OID * class_oid_p, OID * rep_dir_p, bool lookup_hash)
1801 {
1803  PAGE_PTR page_p;
1804  CLS_INFO class_info = CLS_INFO_INITIALIZER;
1805 
1806  HEAP_SCANCACHE scan_cache;
1807  RECDES record = { -1, -1, REC_HOME, NULL };
1808  int error_code = NO_ERROR;
1809 
1810  assert (class_oid_p != NULL);
1811  assert (!OID_ISNULL (class_oid_p));
1812  assert (rep_dir_p != NULL);
1813  assert (OID_ISNULL (rep_dir_p));
1814 
1815  /* 1st try: look up class_info record in Catalog hash */
1816 
1817  assert (repr_item.repr_id == NULL_REPRID);
1818  repr_item.repr_id = NULL_REPRID;
1819  if (lookup_hash == true && catalog_get_representation_item (thread_p, class_oid_p, &repr_item) == NO_ERROR
1820  && !VPID_ISNULL (&(repr_item.page_id)))
1821  {
1822  page_p = pgbuf_fix (thread_p, &repr_item.page_id, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
1823  if (page_p == NULL)
1824  {
1825  assert (er_errid () != NO_ERROR);
1826  error_code = er_errid ();
1827 
1828  return error_code;
1829  }
1830 
1831  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
1832 
1833  if (spage_get_record (thread_p, page_p, repr_item.slot_id, &record, PEEK) != S_SUCCESS)
1834  {
1835  assert (er_errid () != NO_ERROR);
1836  error_code = er_errid ();
1837 
1838  pgbuf_unfix_and_init (thread_p, page_p);
1839 
1840  return error_code;
1841  }
1842 
1843  catalog_get_class_info_from_record (&class_info, record.data);
1844 
1845  pgbuf_unfix_and_init (thread_p, page_p);
1846 
1847  assert (!OID_ISNULL (&(class_info.ci_rep_dir)));
1848  COPY_OID (rep_dir_p, &(class_info.ci_rep_dir));
1849  }
1850 
1851  if (OID_ISNULL (rep_dir_p))
1852  {
1853  /* 2nd try: look up class record in Rootclass */
1854 
1855  heap_scancache_quick_start_root_hfid (thread_p, &scan_cache);
1856 
1857  if (heap_get_class_record (thread_p, class_oid_p, &record, &scan_cache, PEEK) == S_SUCCESS)
1858  {
1859  or_class_rep_dir (&record, rep_dir_p);
1860  }
1861 
1862  heap_scancache_end (thread_p, &scan_cache);
1863  }
1864 
1865  if (OID_ISNULL (rep_dir_p))
1866  {
1867  assert (er_errid () != NO_ERROR);
1868  error_code = er_errid ();
1869 
1870  return error_code;
1871  }
1872 
1873  assert (error_code == NO_ERROR);
1874 
1875  return error_code;
1876 }
1877 
1878 static PAGE_PTR
1879 catalog_get_representation_record (THREAD_ENTRY * thread_p, OID * rep_dir_p, RECDES * record_p, PGBUF_LATCH_MODE latch,
1880  int is_peek, int *out_repr_count_p)
1881 {
1882  PAGE_PTR page_p;
1883  VPID vpid;
1884 
1885  assert (rep_dir_p != NULL);
1886  assert (!OID_ISNULL (rep_dir_p));
1887 
1888  vpid.volid = rep_dir_p->volid;
1889  vpid.pageid = rep_dir_p->pageid;
1890 
1891  page_p = pgbuf_fix (thread_p, &vpid, OLD_PAGE, latch, PGBUF_UNCONDITIONAL_LATCH);
1892  if (page_p == NULL)
1893  {
1894  if (er_errid () == ER_PB_BAD_PAGEID)
1895  {
1897  rep_dir_p->slotid);
1898  }
1899  return NULL;
1900  }
1901 
1902  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
1903 
1904  if (spage_get_record (thread_p, page_p, rep_dir_p->slotid, record_p, is_peek) != S_SUCCESS)
1905  {
1906  pgbuf_unfix_and_init (thread_p, page_p);
1907  return NULL;
1908  }
1909 
1910  assert (record_p->length == CATALOG_REPR_ITEM_SIZE * 2);
1911 
1912  *out_repr_count_p = CATALOG_GET_REPR_ITEM_COUNT (record_p->data);
1913  assert (*out_repr_count_p == 1 || *out_repr_count_p == 2);
1914 
1915  return page_p;
1916 }
1917 
1918 static PAGE_PTR
1920  PGBUF_LATCH_MODE latch, int is_peek, OID * rep_dir_p,
1921  int *out_repr_count_p, bool lookup_hash)
1922 {
1923  assert (class_id_p != NULL);
1924  assert (!OID_ISNULL (class_id_p));
1925  assert (rep_dir_p != NULL);
1926  assert (OID_ISNULL (rep_dir_p));
1927 
1928  /* get old directory for the class */
1929  if (catalog_get_rep_dir (thread_p, class_id_p, rep_dir_p, lookup_hash) != NO_ERROR || OID_ISNULL (rep_dir_p))
1930  {
1931  assert (er_errid () != NO_ERROR);
1932  return NULL;
1933  }
1934 
1935  return catalog_get_representation_record (thread_p, rep_dir_p, record_p, latch, is_peek, out_repr_count_p);
1936 }
1937 
1938 static int
1939 catalog_adjust_directory_count (THREAD_ENTRY * thread_p, PAGE_PTR page_p, RECDES * record_p, int delta)
1940 {
1941  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
1942 
1943  spage_get_record (thread_p, page_p, CATALOG_HEADER_SLOT, record_p, COPY);
1944 
1945  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, CATALOG_HEADER_SLOT, record_p);
1946 
1948 
1949  if (spage_update (thread_p, page_p, CATALOG_HEADER_SLOT, record_p) != SP_SUCCESS)
1950  {
1951  return ER_FAILED;
1952  }
1953 
1954  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, CATALOG_HEADER_SLOT, record_p);
1955 
1956  return NO_ERROR;
1957 }
1958 
1959 static void
1960 catalog_delete_key (THREAD_ENTRY * thread_p, OID * class_id_p, REPR_ID repr_id)
1961 {
1963 
1964  catalog_key.page_id = class_id_p->pageid;
1965  catalog_key.volid = class_id_p->volid;
1966  catalog_key.slot_id = class_id_p->slotid;
1967  catalog_key.repr_id = repr_id;
1968 
1969  (void) catalog_Hashmap.erase (thread_p, catalog_key);
1970 }
1971 
1972 static char *
1973 catalog_find_representation_item_position (INT16 repr_id, int repr_cnt, char *repr_p, int *out_position_p)
1974 {
1975  int position = 0;
1976 
1977  while (position < repr_cnt && repr_id != CATALOG_GET_REPR_ITEM_REPRID (repr_p))
1978  {
1979  position++;
1980  repr_p += CATALOG_REPR_ITEM_SIZE;
1981  }
1982 
1983  *out_position_p = position;
1984  assert (*out_position_p <= 2); /* class info repr, last repr */
1985 
1986  return repr_p;
1987 }
1988 
1989 static int
1990 catalog_insert_representation_item (THREAD_ENTRY * thread_p, RECDES * record_p, OID * rep_dir_p)
1991 {
1992  PAGE_PTR page_p;
1993  VPID page_id;
1994  PGSLOTID slot_id;
1995  PGLENGTH new_space;
1996 
1997  assert (record_p != NULL);
1998  assert (OR_GET_BYTE (record_p->data + CATALOG_REPR_ITEM_COUNT_OFF) == 1);
1999  assert (record_p->length == CATALOG_REPR_ITEM_SIZE * 2);
2000 
2001  assert (rep_dir_p != NULL);
2002  assert (OID_ISNULL (rep_dir_p));
2003 
2004  page_p = catalog_find_optimal_page (thread_p, record_p->length, &page_id);
2005  if (page_p == NULL)
2006  {
2007  return ER_FAILED;
2008  }
2009 
2010  if (spage_insert (thread_p, page_p, record_p, &slot_id) != SP_SUCCESS)
2011  {
2012  pgbuf_unfix_and_init (thread_p, page_p);
2013  return ER_FAILED;
2014  }
2015 
2016  log_append_undoredo_recdes2 (thread_p, RVCT_INSERT, &catalog_Id.vfid, page_p, slot_id, NULL, record_p);
2017 
2018  if (catalog_adjust_directory_count (thread_p, page_p, record_p, 1) != NO_ERROR)
2019  {
2020  pgbuf_unfix_and_init (thread_p, page_p);
2021  return ER_FAILED;
2022  }
2023 
2024  new_space = spage_max_space_for_new_record (thread_p, page_p);
2025  pgbuf_set_dirty (thread_p, page_p, FREE);
2026  catalog_update_max_space (&page_id, new_space);
2027 
2028  rep_dir_p->volid = page_id.volid;
2029  rep_dir_p->pageid = page_id.pageid;
2030  rep_dir_p->slotid = slot_id;
2031 
2032  if (OID_ISNULL (rep_dir_p))
2033  {
2034  assert (false); /* is impossible */
2035 
2036  return ER_FAILED;
2037  }
2038 
2039  return NO_ERROR;
2040 }
2041 
2042 
2043 /*
2044  * catalog_put_representation_item () -
2045  * return: NO_ERROR or ER_FAILED
2046  * class_id_p(in): Class object identifier
2047  * repr_item_p(in): Representation Item
2048  * rep_dir_p(in/out): Representation Directory
2049  *
2050  * Note: The given representation item is inserted to the class
2051  * directory, if any. If there is no class directory, one is
2052  * created to contain the given item.
2053  * If there is already a class directory, the given
2054  * item replaces the old representation item with the same
2055  * representation identifier, if any, otherwise it is added to
2056  * the directory.
2057  */
2058 static int
2059 catalog_put_representation_item (THREAD_ENTRY * thread_p, OID * class_id_p, CATALOG_REPR_ITEM * repr_item_p,
2060  OID * rep_dir_p)
2061 {
2062  PAGE_PTR page_p;
2063  VPID page_id;
2064  PGSLOTID slot_id;
2065 #if 0 /* TODO - dead code; do not delete me for future use */
2066  PGLENGTH new_space;
2067  char page_header_data[CATALOG_PAGE_HEADER_SIZE + MAX_ALIGNMENT];
2068  char *aligned_page_header_data;
2069 #endif
2070  RECDES record = { 0, -1, REC_HOME, NULL };
2071  RECDES tmp_record = { 0, -1, REC_HOME, NULL };
2072  int repr_pos, repr_count;
2073  char *repr_p;
2074  int success;
2075 
2076  assert (rep_dir_p != NULL);
2077 
2078 #if 0 /* TODO - dead code; do not delete me for future use */
2079  aligned_page_header_data = PTR_ALIGN (page_header_data, MAX_ALIGNMENT);
2080 #endif
2081 
2083  {
2084  return ER_FAILED;
2085  }
2086 
2087  /* add new directory for the class */
2088  if (OID_ISNULL (rep_dir_p))
2089  {
2090  record.length = CATALOG_REPR_ITEM_SIZE * 2;
2091  catalog_put_repr_item_to_record (record.data, repr_item_p);
2092 
2093  /* save #repr */
2095  assert (record.length == CATALOG_REPR_ITEM_SIZE * 2);
2096 
2097  if (catalog_insert_representation_item (thread_p, &record, rep_dir_p) != NO_ERROR || OID_ISNULL (rep_dir_p))
2098  {
2099  recdes_free_data_area (&record);
2100  return ER_FAILED;
2101  }
2102 
2103  assert (!OID_ISNULL (rep_dir_p));
2104  }
2105  else
2106  {
2107  /* get old directory for the class */
2108  page_id.volid = rep_dir_p->volid;
2109  page_id.pageid = rep_dir_p->pageid;
2110 
2111  page_p = catalog_get_representation_record (thread_p, rep_dir_p, &record, PGBUF_LATCH_WRITE, COPY, &repr_count);
2112  if (page_p == NULL)
2113  {
2114  recdes_free_data_area (&record);
2115  return ER_FAILED;
2116  }
2117 
2118  repr_p = catalog_find_representation_item_position (repr_item_p->repr_id, repr_count, record.data, &repr_pos);
2119 
2120  if (repr_pos < repr_count)
2121  {
2122  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir_p->slotid, &record);
2123 
2124  page_id.pageid = CATALOG_GET_REPR_ITEM_PAGEID_PAGEID (repr_p);
2125  page_id.volid = CATALOG_GET_REPR_ITEM_PAGEID_VOLID (repr_p);
2126  slot_id = CATALOG_GET_REPR_ITEM_SLOTID (repr_p);
2127 
2128  catalog_delete_key (thread_p, class_id_p, repr_item_p->repr_id);
2129  catalog_put_repr_item_to_record (repr_p, repr_item_p);
2130 
2131  /* save #repr */
2132  OR_PUT_BYTE (record.data + CATALOG_REPR_ITEM_COUNT_OFF, repr_count);
2133  assert (record.length == CATALOG_REPR_ITEM_SIZE * 2);
2134 
2135  if (spage_update (thread_p, page_p, rep_dir_p->slotid, &record) != SP_SUCCESS)
2136  {
2137  recdes_free_data_area (&record);
2138  pgbuf_unfix_and_init (thread_p, page_p);
2139  return ER_FAILED;
2140  }
2141 
2142  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir_p->slotid, &record);
2143  pgbuf_set_dirty (thread_p, page_p, FREE);
2144 
2145  /* delete the old representation */
2146  if (catalog_drop_disk_representation_from_page (thread_p, &page_id, slot_id) != NO_ERROR)
2147  {
2148  recdes_free_data_area (&record);
2149  return ER_FAILED;
2150  }
2151  }
2152  else /* a new representation identifier */
2153  {
2154  assert (repr_count == 1);
2155 
2156  /* copy old directory for logging purposes */
2157 
2158  if (recdes_allocate_data_area (&tmp_record, record.length) != NO_ERROR)
2159  {
2160  pgbuf_unfix_and_init (thread_p, page_p);
2161  recdes_free_data_area (&record);
2162  return ER_FAILED;
2163  }
2164 
2165  tmp_record.length = record.length;
2166  tmp_record.type = record.type;
2167  memcpy (tmp_record.data, record.data, record.length);
2168 
2169  /* add the new representation item */
2171  /* save #repr */
2172  OR_PUT_BYTE (record.data + CATALOG_REPR_ITEM_COUNT_OFF, repr_count + 1);
2174  assert (record.length == CATALOG_REPR_ITEM_SIZE * 2);
2175 
2176  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir_p->slotid, &tmp_record);
2177 
2178  success = spage_update (thread_p, page_p, rep_dir_p->slotid, &record);
2179  if (success == SP_SUCCESS)
2180  {
2181  recdes_free_data_area (&tmp_record);
2182  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir_p->slotid, &record);
2183  pgbuf_set_dirty (thread_p, page_p, FREE);
2184  }
2185 #if 0 /* TODO - dead code; do not delete me for future use */
2186  else if (success == SP_DOESNT_FIT)
2187  {
2188  assert (false); /* is impossible */
2189 
2190  /* the directory needs to be deleted from the current page and moved to another page. */
2191 
2192  ehash_delete (thread_p, &catalog_Id.xhid, key);
2193  log_append_undoredo_recdes2 (thread_p, RVCT_DELETE, &catalog_Id.vfid, page_p, rep_dir_p->slotid,
2194  &tmp_record, NULL);
2195  recdes_free_data_area (&tmp_record);
2196 
2197  spage_delete (thread_p, page_p, rep_dir_p->slotid);
2198  new_space = spage_max_space_for_new_record (thread_p, page_p);
2199 
2200  recdes_set_data_area (&tmp_record, aligned_page_header_data, CATALOG_PAGE_HEADER_SIZE);
2201 
2202  if (catalog_adjust_directory_count (thread_p, page_p, &tmp_record, -1) != NO_ERROR)
2203  {
2204  pgbuf_unfix_and_init (thread_p, page_p);
2205  recdes_free_data_area (&record);
2206  return ER_FAILED;
2207  }
2208 
2209  pgbuf_set_dirty (thread_p, page_p, FREE);
2210  catalog_update_max_space (&page_id, new_space);
2211 
2212  if (catalog_insert_representation_item (thread_p, &record, rep_dir_p) != NO_ERROR)
2213  {
2214  recdes_free_data_area (&record);
2215  return ER_FAILED;
2216  }
2217  }
2218 #endif
2219  else
2220  {
2221  assert (false); /* is impossible */
2222 
2223  pgbuf_unfix_and_init (thread_p, page_p);
2224  recdes_free_data_area (&tmp_record);
2225  recdes_free_data_area (&record);
2226  return ER_FAILED;
2227  }
2228  }
2229  }
2230 
2231  recdes_free_data_area (&record);
2232 
2233  return NO_ERROR;
2234 }
2235 
2236 /*
2237  * catalog_get_representation_item () -
2238  * return: NO_ERROR or ER_FAILED
2239  * class_id(in): Class object identifier
2240  * repr_item(in/out): Set to the Representation Item
2241  * (repr_item->repr_id must be set by the caller)
2242  *
2243  * Note: The representation item for the given class and the specified
2244  * representation identifier (set by the caller in repr_item) is
2245  * extracted from the class directory. This information tells
2246  * the caller where, in the catalog, the specifed represenation unit resides.
2247  */
2248 static int
2249 catalog_get_representation_item (THREAD_ENTRY * thread_p, OID * class_id_p, CATALOG_REPR_ITEM * repr_item_p)
2250 {
2251  PAGE_PTR page_p;
2252  RECDES record;
2253  OID rep_dir;
2254  CATALOG_ENTRY *catalog_value_p;
2255  int repr_pos, repr_count;
2256  char *repr_p;
2258 
2259  OID_SET_NULL (&rep_dir); /* init */
2260 
2261  catalog_key.page_id = class_id_p->pageid;
2262  catalog_key.volid = class_id_p->volid;
2263  catalog_key.slot_id = class_id_p->slotid;
2264  catalog_key.repr_id = repr_item_p->repr_id;
2265 
2266  catalog_value_p = catalog_Hashmap.find (thread_p, catalog_key);
2267  if (catalog_value_p != NULL)
2268  {
2269  /* entry already exists */
2270  repr_item_p->page_id.volid = catalog_value_p->key.r_page_id.volid;
2271  repr_item_p->page_id.pageid = catalog_value_p->key.r_page_id.pageid;
2272  repr_item_p->slot_id = catalog_value_p->key.r_slot_id;
2273 
2274  /* end transaction */
2275  catalog_Hashmap.unlock (thread_p, catalog_value_p);
2276  return NO_ERROR;
2277  }
2278  else
2279  {
2280  /* fresh entry, fetch data for it */
2281 
2282  assert (OID_ISNULL (&rep_dir));
2283 
2284  page_p =
2285  catalog_get_representation_record_after_search (thread_p, class_id_p, &record, PGBUF_LATCH_READ, PEEK, &rep_dir,
2286  &repr_count, false /* lookup_hash */ );
2287  if (page_p == NULL)
2288  {
2289  return ER_FAILED;
2290  }
2291 
2292  repr_p = catalog_find_representation_item_position (repr_item_p->repr_id, repr_count, record.data, &repr_pos);
2293 
2294  if (repr_pos == repr_count)
2295  {
2296  pgbuf_unfix_and_init (thread_p, page_p);
2298  return ER_FAILED;
2299  }
2300 
2301  repr_item_p->page_id.pageid = CATALOG_GET_REPR_ITEM_PAGEID_PAGEID (repr_p);
2302  repr_item_p->page_id.volid = CATALOG_GET_REPR_ITEM_PAGEID_VOLID (repr_p);
2303  repr_item_p->slot_id = CATALOG_GET_REPR_ITEM_SLOTID (repr_p);
2304  pgbuf_unfix_and_init (thread_p, page_p);
2305 
2306  /* set entry info for further use */
2307  catalog_key.r_page_id.pageid = repr_item_p->page_id.pageid;
2308  catalog_key.r_page_id.volid = repr_item_p->page_id.volid;
2309  catalog_key.r_slot_id = repr_item_p->slot_id;
2310 
2311  /* insert value */
2312  catalog_Hashmap.find_or_insert (thread_p, catalog_key, catalog_value_p);
2313  if (catalog_value_p != NULL)
2314  {
2315  catalog_Hashmap.unlock (thread_p, catalog_value_p);
2316  return NO_ERROR;
2317  }
2318  else
2319  {
2320  /* impossible case */
2321 #if defined(CT_DEBUG)
2323  "catalog_get_representation_item: Insertion to hash table failed.\n "
2324  "Key: Class_Id: { %d , %d , %d } Repr: %d", class_id_p->pageid, class_id_p->volid,
2325  class_id_p->slotid, repr_item_p->repr_id);
2326 #endif /* CT_DEBUG */
2327  assert (false);
2328  return ER_FAILED;
2329  }
2330  }
2331 }
2332 
2333 static int
2334 catalog_drop_directory (THREAD_ENTRY * thread_p, PAGE_PTR page_p, RECDES * record_p, OID * oid_p, OID * class_id_p)
2335 {
2336  log_append_undoredo_recdes2 (thread_p, RVCT_DELETE, &catalog_Id.vfid, page_p, oid_p->slotid, record_p, NULL);
2337 
2338  if (spage_delete (thread_p, page_p, oid_p->slotid) != oid_p->slotid)
2339  {
2340  return ER_FAILED;
2341  }
2342 
2343  if (catalog_adjust_directory_count (thread_p, page_p, record_p, -1) != NO_ERROR)
2344  {
2345  return ER_FAILED;
2346  }
2347 
2348  return NO_ERROR;
2349 }
2350 
2351 /*
2352  * catalog_drop_representation_item () -
2353  * return: NO_ERROR or ER_FAILED
2354  * class_id(in): Class object identifier
2355  * repr_item(in): Representation Item
2356  * (repr_item->repr_id must be set by the caller)
2357  *
2358  * Note: The representation item for the given class and the specified
2359  * representation identifier (set by the caller in repr_item) is
2360  * dropped from the class directory.
2361  */
2362 static int
2363 catalog_drop_representation_item (THREAD_ENTRY * thread_p, OID * class_id_p, CATALOG_REPR_ITEM * repr_item_p)
2364 {
2365  PAGE_PTR page_p;
2366  PGLENGTH new_space;
2367  char *repr_p, *next_p;
2368  int repr_pos, repr_count;
2369  RECDES record;
2370  OID rep_dir;
2371  VPID vpid;
2373 
2374  OID_SET_NULL (&rep_dir); /* init */
2375 
2377  {
2378  return ER_FAILED;
2379  }
2380 
2381  page_p =
2382  catalog_get_representation_record_after_search (thread_p, class_id_p, &record, PGBUF_LATCH_WRITE, COPY, &rep_dir,
2383  &repr_count, true /* lookup_hash */ );
2384  if (page_p == NULL)
2385  {
2386  recdes_free_data_area (&record);
2387  return ER_FAILED;
2388  }
2389 
2390  repr_p = catalog_find_representation_item_position (repr_item_p->repr_id, repr_count, record.data, &repr_pos);
2391 
2392  if (repr_pos >= repr_count)
2393  {
2394  pgbuf_unfix_and_init (thread_p, page_p);
2395  recdes_free_data_area (&record);
2397  return ER_FAILED;
2398  }
2399 
2400  repr_item_p->page_id.pageid = CATALOG_GET_REPR_ITEM_PAGEID_PAGEID (repr_p);
2401  repr_item_p->page_id.volid = CATALOG_GET_REPR_ITEM_PAGEID_VOLID (repr_p);
2402  repr_item_p->slot_id = CATALOG_GET_REPR_ITEM_SLOTID (repr_p);
2403 
2404  catalog_delete_key (thread_p, class_id_p, repr_item_p->repr_id);
2405 
2406  if (repr_count > 1)
2407  {
2408  assert (repr_count == 2);
2409 
2410  /* the directory will be updated */
2411 
2412  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir.slotid, &record);
2413 
2414  next_p = repr_p;
2415  for (next_p += CATALOG_REPR_ITEM_SIZE; repr_pos < (repr_count - 1);
2416  repr_pos++, repr_p += CATALOG_REPR_ITEM_SIZE, next_p += CATALOG_REPR_ITEM_SIZE)
2417  {
2418  catalog_get_repr_item_from_record (&tmp_repr_item, next_p);
2419  catalog_put_repr_item_to_record (repr_p, &tmp_repr_item);
2420  }
2421 
2422  /* save #repr */
2423  OR_PUT_BYTE (record.data + CATALOG_REPR_ITEM_COUNT_OFF, repr_count - 1);
2425 
2426  assert (record.length == CATALOG_REPR_ITEM_SIZE * 2);
2427 
2428  if (spage_update (thread_p, page_p, rep_dir.slotid, &record) != SP_SUCCESS)
2429  {
2430  pgbuf_unfix_and_init (thread_p, page_p);
2431  recdes_free_data_area (&record);
2432  return ER_FAILED;
2433  }
2434 
2435  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir.slotid, &record);
2436  }
2437  else
2438  {
2439  if (catalog_drop_directory (thread_p, page_p, &record, &rep_dir, class_id_p) != NO_ERROR)
2440  {
2441  pgbuf_unfix_and_init (thread_p, page_p);
2442  recdes_free_data_area (&record);
2443  return ER_FAILED;
2444  }
2445  }
2446 
2447  new_space = spage_max_space_for_new_record (thread_p, page_p);
2448  pgbuf_set_dirty (thread_p, page_p, FREE);
2449 
2450  vpid.volid = rep_dir.volid;
2451  vpid.pageid = rep_dir.pageid;
2452  catalog_update_max_space (&vpid, new_space);
2453 
2454  recdes_free_data_area (&record);
2455  return NO_ERROR;
2456 }
2457 
2458 static void
2459 catalog_copy_btree_statistic (BTREE_STATS * new_btree_stats_p, int new_btree_stats_count,
2460  BTREE_STATS * pre_btree_stats_p, int pre_btree_stats_count)
2461 {
2462  BTREE_STATS *pre_stats_p, *new_stats_p;
2463  int i, j, k;
2464 
2465  for (i = 0, new_stats_p = new_btree_stats_p; i < new_btree_stats_count; i++, new_stats_p++)
2466  {
2467  for (j = 0, pre_stats_p = pre_btree_stats_p; j < pre_btree_stats_count; j++, pre_stats_p++)
2468  {
2469  if (!BTID_IS_EQUAL (&new_stats_p->btid, &pre_stats_p->btid))
2470  {
2471  continue;
2472  }
2473 
2474  new_stats_p->btid = pre_stats_p->btid;
2475  new_stats_p->leafs = pre_stats_p->leafs;
2476  new_stats_p->pages = pre_stats_p->pages;
2477  new_stats_p->height = pre_stats_p->height;
2478  new_stats_p->keys = pre_stats_p->keys;
2479  new_stats_p->key_type = pre_stats_p->key_type;
2480  new_stats_p->pkeys_size = pre_stats_p->pkeys_size;
2481 
2482  assert (new_stats_p->pkeys_size <= BTREE_STATS_PKEYS_NUM);
2483  for (k = 0; k < new_stats_p->pkeys_size; k++)
2484  {
2485  new_stats_p->pkeys[k] = pre_stats_p->pkeys[k];
2486  }
2487 #if 0 /* reserved for future use */
2488  for (k = 0; k < BTREE_STATS_RESERVED_NUM; k++)
2489  {
2490  new_stats_p->reserved[k] = pre_stats_p->reserved[k];
2491  }
2492 #endif
2493 
2494  break;
2495  }
2496  }
2497 }
2498 
2499 static void
2500 catalog_copy_disk_attributes (DISK_ATTR * new_attrs_p, int new_attr_count, DISK_ATTR * pre_attrs_p, int pre_attr_count)
2501 {
2502  DISK_ATTR *pre_attr_p, *new_attr_p;
2503  int i, j;
2504 
2505  for (i = 0, new_attr_p = new_attrs_p; i < new_attr_count; i++, new_attr_p++)
2506  {
2507  for (j = 0, pre_attr_p = pre_attrs_p; j < pre_attr_count; j++, pre_attr_p++)
2508  {
2509  if (new_attr_p->id != pre_attr_p->id)
2510  {
2511  continue;
2512  }
2513 
2514  catalog_copy_btree_statistic (new_attr_p->bt_stats, new_attr_p->n_btstats, pre_attr_p->bt_stats,
2515  pre_attr_p->n_btstats);
2516  }
2517  }
2518 }
2519 
2520 /*
2521  * Catalog interface routines
2522  */
2523 
2524 /*
2525  * catalog_initialize () - Initialize data for further catalog operations
2526  * return: nothing
2527  * catid(in): Catalog identifier taken from the system page
2528  *
2529  * Note: Creates and initializes a main memory hash table that will be
2530  * used by catalog operations for fast access to catalog data.
2531  * The max_rec_size global variable which shows the maximum
2532  * available space on a catalog page with a header, is set by the
2533  * data in the catalog header. This routine should always be
2534  * called before any other catalog operations, except catalog creation.
2535  */
2536 void
2537 catalog_initialize (CTID * catalog_id_p)
2538 {
2539  // protect against repeated hashmap initializations
2540  catalog_Hashmap.destroy ();
2541 
2542  VFID_COPY (&catalog_Id.xhid, &catalog_id_p->xhid);
2543  catalog_Id.xhid.pageid = catalog_id_p->xhid.pageid;
2544  catalog_Id.vfid.fileid = catalog_id_p->vfid.fileid;
2545  catalog_Id.vfid.volid = catalog_id_p->vfid.volid;
2546  catalog_Id.hpgid = catalog_id_p->hpgid;
2547 
2548  // init
2549  catalog_Hashmap.init (catalog_Ts, THREAD_TS_CATALOG, CATALOG_HASH_SIZE, 2, 100, catalog_entry_Descriptor);
2550 
2553 
2554  if (catalog_is_header_initialized == false)
2555  {
2556  catalog_initialize_max_space (&catalog_Max_space);
2558  }
2559 }
2560 
2561 /*
2562  * catalog_finalize () - Finalize the catalog operations by destroying the catalog
2563  * memory hash table.
2564  * return: nothing
2565  */
2566 void
2568 {
2569  catalog_Hashmap.destroy ();
2570 }
2571 
2572 /*
2573  * catalog_create () -
2574  * return: CTID * (catid on success and NULL on failure)
2575  * catalog_id_p(out): Catalog identifier.
2576  * All the fields in the identifier are set except the catalog
2577  * and catalog index volume identifiers which should have been
2578  * set by the caller.
2579  *
2580  * Note: Creates the catalog and an index that will be used for fast
2581  * catalog search. The index used is an extendible hashing index.
2582  * The first page (header page) of the catalog is allocated and
2583  * catalog header information is initialized.
2584  */
2585 CTID *
2586 catalog_create (THREAD_ENTRY * thread_p, CTID * catalog_id_p)
2587 {
2588  PAGE_PTR page_p;
2589  VPID first_page_vpid;
2590  int new_space;
2591  bool is_overflow_page = false;
2592 
2593  log_sysop_start (thread_p);
2594 
2595  if (xehash_create (thread_p, &catalog_id_p->xhid, DB_TYPE_OBJECT, 1, oid_Root_class_oid, -1, false) == NULL)
2596  {
2597  ASSERT_ERROR ();
2598  goto error;
2599  }
2600 
2601  if (file_create_with_npages (thread_p, FILE_CATALOG, 1, NULL, &catalog_id_p->vfid) != NO_ERROR)
2602  {
2603  ASSERT_ERROR ();
2604  goto error;
2605  }
2606 
2607  if (file_alloc_sticky_first_page (thread_p, &catalog_id_p->vfid, catalog_initialize_new_page, &is_overflow_page,
2608  &first_page_vpid, &page_p) != NO_ERROR)
2609  {
2610  ASSERT_ERROR ();
2611  goto error;
2612  }
2613  if (first_page_vpid.volid != catalog_id_p->vfid.volid)
2614  {
2615  assert_release (false);
2616  goto error;
2617  }
2618  if (page_p == NULL)
2619  {
2620  assert_release (false);
2621  goto error;
2622  }
2623  catalog_id_p->hpgid = first_page_vpid.pageid;
2624 
2625  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
2626 
2627  if (catalog_is_header_initialized == false)
2628  {
2629  catalog_initialize_max_space (&catalog_Max_space);
2631  }
2632 
2633  new_space = spage_max_space_for_new_record (thread_p, page_p);
2634  catalog_update_max_space (&first_page_vpid, new_space);
2635  pgbuf_unfix_and_init (thread_p, page_p);
2636 
2637  /* success */
2638  log_sysop_attach_to_outer (thread_p);
2639 
2640  return catalog_id_p;
2641 
2642 error:
2643  log_sysop_abort (thread_p);
2644 
2645  return NULL;
2646 }
2647 
2648 #if defined (SA_MODE)
2649 /*
2650  * catalog_file_map_is_empty () - FILE_MAP_PAGE_FUNC to check if catalog pages are empty. if true, it is save into a
2651  * collector.
2652  *
2653  * return : NO_ERROR
2654  * thread_p (in) : thread entry
2655  * page (in) : catalog page pointer
2656  * stop (in) : not used
2657  * args (in) : CATALOG_PAGE_COLLECTOR *
2658  */
2659 static int
2660 catalog_file_map_is_empty (THREAD_ENTRY * thread_p, PAGE_PTR * page, bool * stop, void *args)
2661 {
2662  CATALOG_PAGE_COLLECTOR *collector = (CATALOG_PAGE_COLLECTOR *) args;
2663  (void) pgbuf_check_page_ptype (thread_p, *page, PAGE_CATALOG);
2664 
2665  if (spage_number_of_records (*page) <= 1)
2666  {
2667  pgbuf_get_vpid (*page, &collector->vpids[collector->n_vpids++]);
2668  }
2669  return NO_ERROR;
2670 }
2671 #endif /* SA_MODE */
2672 
2673 /*
2674  * catalog_reclaim_space () - Reclaim catalog space by deallocating all the empty
2675  * pages.
2676  * return: NO_ERROR or ER_FAILED
2677  *
2678  * Note: This routine is supposed to be called only OFF-LINE.
2679  */
2680 int
2682 {
2683 #if defined (SA_MODE)
2684  CATALOG_PAGE_COLLECTOR collector;
2685  int n_pages;
2686  int iter_vpid;
2687 
2688  int error_code = NO_ERROR;
2689 
2690  /* reinitialize catalog hinted page information, this is needed since the page pointed by this header may be
2691  * deallocated by this routine and the hinted page structure may have a dangling page pointer. */
2692  catalog_initialize_max_space (&catalog_Max_space);
2693 
2694  error_code = file_get_num_user_pages (thread_p, &catalog_Id.vfid, &n_pages);
2695  if (error_code != NO_ERROR)
2696  {
2697  ASSERT_ERROR ();
2698  return error_code;
2699  }
2700  if (n_pages <= 0)
2701  {
2702  assert_release (false);
2703  return ER_FAILED;
2704  }
2705 
2706  collector.vpids = (VPID *) malloc (n_pages * sizeof (VPID));
2707  if (collector.vpids == NULL)
2708  {
2710  return ER_OUT_OF_VIRTUAL_MEMORY;
2711  }
2712  collector.n_vpids = 0;
2713 
2714  error_code =
2715  file_map_pages (thread_p, &catalog_Id.vfid, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH, catalog_file_map_is_empty,
2716  &collector);
2717  if (error_code != NO_ERROR)
2718  {
2719  ASSERT_ERROR ();
2720  free (collector.vpids);
2721  return error_code;
2722  }
2723 
2724  for (iter_vpid = 0; iter_vpid < collector.n_vpids; iter_vpid++)
2725  {
2726  error_code = file_dealloc (thread_p, &catalog_Id.vfid, &collector.vpids[iter_vpid], FILE_CATALOG);
2727  if (error_code != NO_ERROR)
2728  {
2729  ASSERT_ERROR ();
2730  free (collector.vpids);
2731  return error_code;
2732  }
2733  }
2734  free (collector.vpids);
2735 #endif /* SA_MODE */
2736  return NO_ERROR;
2737 }
2738 
2739 static int
2741 {
2742  int i, j, size = 0;
2743  DISK_ATTR *disk_attrp;
2744 
2745  for (i = 0, disk_attrp = attrs_p; i < count; i++, disk_attrp++)
2746  {
2747  size += CATALOG_DISK_ATTR_SIZE;
2748  size += disk_attrp->val_length + (MAX_ALIGNMENT * 2);
2749  for (j = 0; j < disk_attrp->n_btstats; j++)
2750  {
2751  size += CATALOG_BT_STATS_SIZE;
2752  }
2753  }
2754 
2755  return size;
2756 }
2757 
2758 /*
2759  * catalog_add_representation () - Add disk representation to the catalog
2760  * return: int
2761  * class_id_p(in): Class identifier
2762  * repr_id(in): Disk Representation identifier
2763  * disk_repr_p(in): Pointer to the disk representation structure
2764  * rep_dir_p(in/out): Representation Directory
2765  * catalog_access_info_p(in): access info on catalog; if this is NULL
2766  * locking of directory OID is performed here,
2767  * otherwise the caller is reponsible for
2768  * protecting concurrent access.*
2769  */
2770 int
2771 catalog_add_representation (THREAD_ENTRY * thread_p, OID * class_id_p, REPR_ID repr_id, DISK_REPR * disk_repr_p,
2772  OID * rep_dir_p, CATALOG_ACCESS_INFO * catalog_access_info_p)
2773 {
2776  PAGE_PTR page_p;
2777  PGLENGTH new_space;
2778  VPID vpid;
2779  DISK_ATTR *disk_attr_p;
2780  BTREE_STATS *btree_stats_p;
2781  int size, i, j;
2782  char *data;
2783  PGSLOTID remembered_slot_id = NULL_SLOTID;
2785  OID dir_oid;
2786  int error_code = NO_ERROR;
2787  bool do_end_access = false;
2788 
2789  assert (rep_dir_p != NULL);
2790 
2791  if (OID_ISTEMP (class_id_p))
2792  {
2793  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_INVALID_CLASSID, 3, class_id_p->volid, class_id_p->pageid,
2794  class_id_p->slotid);
2795  return ER_CT_INVALID_CLASSID;
2796  }
2797 
2798  if (repr_id == NULL_REPRID)
2799  {
2801  return ER_CT_INVALID_REPRID;
2802  }
2803 
2804  size = CATALOG_DISK_REPR_SIZE;
2805  size += catalog_sum_disk_attribute_size (disk_repr_p->fixed, disk_repr_p->n_fixed);
2806  size += catalog_sum_disk_attribute_size (disk_repr_p->variable, disk_repr_p->n_variable);
2807 
2808  if (catalog_access_info_p == NULL)
2809  {
2810  do_end_access = true;
2811  error_code = catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid);
2812  if (error_code != NO_ERROR)
2813  {
2814  return error_code;
2815  }
2816 
2817  catalog_access_info.class_oid = class_id_p;
2818  catalog_access_info.dir_oid = &dir_oid;
2819  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
2820  if (error_code != NO_ERROR)
2821  {
2822  return error_code;
2823  }
2824  catalog_access_info_p = &catalog_access_info;
2825  }
2826 
2827  page_p = catalog_find_optimal_page (thread_p, size, &vpid);
2828  if (page_p == NULL)
2829  {
2830  ASSERT_ERROR_AND_SET (error_code);
2831  if (do_end_access)
2832  {
2833  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2834  }
2835  return error_code;
2836  }
2837 
2838  repr_item.page_id.pageid = vpid.pageid;
2839  repr_item.page_id.volid = vpid.volid;
2840  repr_item.slot_id = NULL_SLOTID;
2841  repr_item.repr_id = repr_id;
2842 
2843  data = (char *) db_private_alloc (thread_p, DB_PAGESIZE);
2844  if (!data)
2845  {
2846  if (do_end_access)
2847  {
2848  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2849  }
2850  return ER_OUT_OF_VIRTUAL_MEMORY;
2851  }
2852 
2853  catalog_record.vpid.pageid = repr_item.page_id.pageid;
2854  catalog_record.vpid.volid = repr_item.page_id.volid;
2855  catalog_record.slotid = NULL_SLOTID;
2856  catalog_record.page_p = page_p;
2857  catalog_record.recdes.area_size = spage_max_space_for_new_record (thread_p, page_p) - CATALOG_MAX_SLOT_ID_SIZE;
2858  catalog_record.recdes.length = 0;
2859  catalog_record.recdes.type = REC_HOME;
2860  catalog_record.recdes.data = data;
2861  catalog_record.offset = 0;
2862 
2863  if (catalog_store_disk_representation (thread_p, disk_repr_p, &catalog_record, &remembered_slot_id) != NO_ERROR)
2864  {
2865  db_private_free_and_init (thread_p, data);
2866  ASSERT_ERROR_AND_SET (error_code);
2867  if (do_end_access)
2868  {
2869  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2870  }
2871  return error_code;
2872  }
2873 
2874  new_space = spage_max_space_for_new_record (thread_p, catalog_record.page_p);
2875  catalog_update_max_space (&repr_item.page_id, new_space);
2876 
2877  for (i = 0; i < disk_repr_p->n_fixed + disk_repr_p->n_variable; i++)
2878  {
2879  if (i < disk_repr_p->n_fixed)
2880  {
2881  disk_attr_p = &disk_repr_p->fixed[i];
2882  }
2883  else
2884  {
2885  disk_attr_p = &disk_repr_p->variable[i - disk_repr_p->n_fixed];
2886  }
2887 
2888  if (catalog_store_disk_attribute (thread_p, disk_attr_p, &catalog_record, &remembered_slot_id) != NO_ERROR)
2889  {
2890  db_private_free_and_init (thread_p, data);
2891 
2892  ASSERT_ERROR_AND_SET (error_code);
2893  if (do_end_access)
2894  {
2895  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2896  }
2897  return error_code;
2898  }
2899 
2900  if (catalog_store_attribute_value (thread_p, disk_attr_p->value, disk_attr_p->val_length, &catalog_record,
2901  &remembered_slot_id) != NO_ERROR)
2902  {
2903  db_private_free_and_init (thread_p, data);
2904 
2905  ASSERT_ERROR_AND_SET (error_code);
2906  if (do_end_access)
2907  {
2908  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2909  }
2910  return error_code;
2911  }
2912 
2913  for (j = 0; j < disk_attr_p->n_btstats; j++)
2914  {
2915  btree_stats_p = &disk_attr_p->bt_stats[j];
2916 
2917  assert (btree_stats_p->pkeys_size <= BTREE_STATS_PKEYS_NUM);
2918  if (catalog_store_btree_statistics (thread_p, btree_stats_p, &catalog_record, &remembered_slot_id) !=
2919  NO_ERROR)
2920  {
2921  db_private_free_and_init (thread_p, data);
2922 
2923  ASSERT_ERROR_AND_SET (error_code);
2924  if (do_end_access)
2925  {
2926  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2927  }
2928  return error_code;
2929  }
2930  }
2931  }
2932 
2933  catalog_record.recdes.length = catalog_record.offset;
2934  catalog_record.offset = catalog_record.recdes.area_size;
2935 
2936  if (catalog_put_record_into_page (thread_p, &catalog_record, 0, &remembered_slot_id) != NO_ERROR)
2937  {
2938  db_private_free_and_init (thread_p, data);
2939 
2940  ASSERT_ERROR_AND_SET (error_code);
2941  if (do_end_access)
2942  {
2943  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2944  }
2945  return error_code;
2946  }
2947 
2948  pgbuf_unfix_and_init (thread_p, catalog_record.page_p);
2949 
2950  repr_item.slot_id = catalog_record.slotid;
2951  if (catalog_put_representation_item (thread_p, class_id_p, &repr_item, rep_dir_p) != NO_ERROR
2952  || OID_ISNULL (rep_dir_p))
2953  {
2954  db_private_free_and_init (thread_p, data);
2955 
2956  ASSERT_ERROR_AND_SET (error_code);
2957  if (do_end_access)
2958  {
2959  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
2960  }
2961  return error_code;
2962  }
2963 
2964  if (do_end_access)
2965  {
2966  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, NO_ERROR);
2967  }
2968 
2969  db_private_free_and_init (thread_p, data);
2970 
2971  return NO_ERROR;
2972 }
2973 
2974 /*
2975  * catalog_add_class_info () - Add class information to the catalog
2976  * return: int
2977  * class_id_p(in): Class identifier
2978  * class_info_p(in): Pointer to class specific information structure
2979  * catalog_access_info_p(in): access info on catalog; if this is NULL
2980  * locking of directory OID is performed here,
2981  * otherwise the caller is reponsible for
2982  * protecting concurrent access.
2983  */
2984 int
2985 catalog_add_class_info (THREAD_ENTRY * thread_p, OID * class_id_p, CLS_INFO * class_info_p,
2986  CATALOG_ACCESS_INFO * catalog_access_info_p)
2987 {
2988  PAGE_PTR page_p;
2989  VPID page_id;
2990  PGLENGTH new_space;
2991  RECDES record = { -1, -1, REC_HOME, NULL };
2994  OID dir_oid;
2995  int success;
2996  int error_code;
2997  bool do_end_access = false;
2998 
2999  assert (class_info_p != NULL);
3000  assert (!OID_ISNULL (&(class_info_p->ci_rep_dir)));
3001 
3002  OID_SET_NULL (&dir_oid);
3003 
3004  if (OID_ISTEMP (class_id_p))
3005  {
3006  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_INVALID_CLASSID, 3, class_id_p->volid, class_id_p->pageid,
3007  class_id_p->slotid);
3008  return ER_CT_INVALID_CLASSID;
3009  }
3010 
3011  assert (repr_item.repr_id == NULL_REPRID);
3012 
3013  if (catalog_access_info_p == NULL)
3014  {
3015  do_end_access = true;
3016  error_code = catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid);
3017  if (error_code != NO_ERROR)
3018  {
3019  return error_code;
3020  }
3021 
3022  catalog_access_info.class_oid = class_id_p;
3023  catalog_access_info.dir_oid = &dir_oid;
3024  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
3025  if (error_code != NO_ERROR)
3026  {
3027  return error_code;
3028  }
3029  catalog_access_info_p = &catalog_access_info;
3030  }
3031 
3032  page_p = catalog_find_optimal_page (thread_p, CATALOG_CLS_INFO_SIZE, &page_id);
3033  if (page_p == NULL)
3034  {
3035  ASSERT_ERROR_AND_SET (error_code);
3036  if (do_end_access)
3037  {
3038  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3039  }
3040  return error_code;
3041  }
3042 
3043  repr_item.page_id = page_id;
3044 
3046  {
3047  ASSERT_ERROR_AND_SET (error_code);
3048  if (do_end_access)
3049  {
3050  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3051  }
3052  return error_code;
3053  }
3054 
3055  /* copy the given representation into a slotted page record */
3056  record.length = CATALOG_CLS_INFO_SIZE;
3057  catalog_put_class_info_to_record (record.data, class_info_p);
3059 
3060  success = spage_insert (thread_p, page_p, &record, &repr_item.slot_id);
3061  if (success != SP_SUCCESS)
3062  {
3063  pgbuf_unfix_and_init (thread_p, page_p);
3064  recdes_free_data_area (&record);
3065 
3066  ASSERT_ERROR_AND_SET (error_code);
3067  if (do_end_access)
3068  {
3069  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3070  }
3071  return error_code;
3072  }
3073 
3074  log_append_undoredo_recdes2 (thread_p, RVCT_INSERT, &catalog_Id.vfid, page_p, repr_item.slot_id, NULL, &record);
3075 
3076  new_space = spage_max_space_for_new_record (thread_p, page_p);
3077  pgbuf_set_dirty (thread_p, page_p, FREE);
3078 
3079  catalog_update_max_space (&repr_item.page_id, new_space);
3080 
3081  if (catalog_put_representation_item (thread_p, class_id_p, &repr_item, &(class_info_p->ci_rep_dir)) != NO_ERROR)
3082  {
3083  recdes_free_data_area (&record);
3084 
3085  ASSERT_ERROR_AND_SET (error_code);
3086  if (do_end_access)
3087  {
3088  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3089  }
3090  return error_code;
3091  }
3092 
3093  if (do_end_access)
3094  {
3095  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, NO_ERROR);
3096  }
3097 
3098  recdes_free_data_area (&record);
3099 
3100  return NO_ERROR;
3101 }
3102 
3103 /*
3104  * catalog_update_class_info () - Update class information to the catalog
3105  * return: CLS_INFO* or NULL
3106  * class_id(in): Class identifier
3107  * cls_info(in): Pointer to class specific information structure
3108  * catalog_access_info_p(in): access info on catalog; if this is NULL
3109  * locking of directory OID is performed here,
3110  * otherwise the caller is reponsible for
3111  * protecting concurrent access.
3112  * skip_logging(in): true for skip logging. Otherwise, false
3113  *
3114  * Note: The given class specific information structure is used to
3115  * update existing class specific information. On success, it
3116  * returns the cls_info parameter itself, on failure it returns NULL.
3117  *
3118  * Note: This routine assumes that cls_info structure is of fixed size, ie.
3119  * the new record size is equal to the old record size, therefore it is
3120  * possible to update the old record in_place without moving.
3121  *
3122  * Note: The skip_logging parameter of the function may have FALSE value
3123  * in most cases. However it may have TRUE value in exceptional cases such as
3124  * the locator_increase_catalog_count() or locator_decrease_catalog_count().
3125  * Be sure that no log will be made when the parameter is TRUE.
3126  */
3127 CLS_INFO *
3128 catalog_update_class_info (THREAD_ENTRY * thread_p, OID * class_id_p, CLS_INFO * class_info_p,
3129  CATALOG_ACCESS_INFO * catalog_access_info_p, bool skip_logging)
3130 {
3131  PAGE_PTR page_p;
3132  char data[CATALOG_CLS_INFO_SIZE + MAX_ALIGNMENT], *aligned_data;
3135  LOG_DATA_ADDR addr;
3137  OID dir_oid;
3138  bool do_end_access = false;
3139 
3140  assert (class_info_p != NULL);
3141  assert (!OID_ISNULL (&(class_info_p->ci_rep_dir)));
3142 
3143  if (catalog_access_info_p == NULL)
3144  {
3145  do_end_access = true;
3146  if (catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid) != NO_ERROR)
3147  {
3148  return NULL;
3149  }
3150 
3151  catalog_access_info.class_oid = class_id_p;
3152  catalog_access_info.dir_oid = &dir_oid;
3153  if (catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK) != NO_ERROR)
3154  {
3155  return NULL;
3156  }
3157  catalog_access_info_p = &catalog_access_info;
3158  }
3159 
3160  aligned_data = PTR_ALIGN (data, MAX_ALIGNMENT);
3161 
3162  assert (repr_item.repr_id == NULL_REPRID);
3163  repr_item.repr_id = NULL_REPRID;
3164  if (catalog_get_representation_item (thread_p, class_id_p, &repr_item) != NO_ERROR)
3165  {
3166  if (do_end_access)
3167  {
3168  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3169  }
3170  return NULL;
3171  }
3172 
3173  page_p = pgbuf_fix (thread_p, &repr_item.page_id, OLD_PAGE, PGBUF_LATCH_WRITE, PGBUF_UNCONDITIONAL_LATCH);
3174  if (page_p == NULL)
3175  {
3176  if (do_end_access)
3177  {
3178  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3179  }
3180  return NULL;
3181  }
3182 
3183  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
3184 
3185  recdes_set_data_area (&record, aligned_data, CATALOG_CLS_INFO_SIZE);
3186  if (spage_get_record (thread_p, page_p, repr_item.slot_id, &record, COPY) != S_SUCCESS)
3187  {
3188 #if defined(CT_DEBUG)
3189  if (er_errid () == ER_SP_UNKNOWN_SLOTID)
3190  er_log_debug (ARG_FILE_LINE, "catalog_update_class_info: ",
3191  "no class information record found in catalog.\n"
3192  "possibly catalog index points to a non_existent disk repr.\n");
3193 #endif /* CT_DEBUG */
3194  pgbuf_unfix_and_init (thread_p, page_p);
3195  if (do_end_access)
3196  {
3197  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3198  }
3199  return NULL;
3200  }
3201 
3202  if (skip_logging != true)
3203  {
3204  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, repr_item.slot_id, &record);
3205  }
3206 
3207  catalog_put_class_info_to_record (record.data, class_info_p);
3209 
3210  if (spage_update (thread_p, page_p, repr_item.slot_id, &record) != SP_SUCCESS)
3211  {
3212  pgbuf_unfix_and_init (thread_p, page_p);
3213  if (do_end_access)
3214  {
3215  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3216  }
3217  return NULL;
3218  }
3219 
3220  if (skip_logging != true)
3221  {
3222  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, repr_item.slot_id, &record);
3223  }
3224 
3225  if (skip_logging == true)
3226  {
3227  addr.vfid = &catalog_Id.vfid;
3228  addr.pgptr = page_p;
3229  addr.offset = repr_item.slot_id;
3230 
3231  log_skip_logging (thread_p, &addr);
3232  }
3233  pgbuf_set_dirty (thread_p, page_p, FREE);
3234  if (do_end_access)
3235  {
3236  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, NO_ERROR);
3237  }
3238 
3239  return class_info_p;
3240 }
3241 
3242 /*
3243  * catalog_drop () - Drop representation/class information from catalog
3244  * return: int
3245  * class_id(in): Class identifier
3246  * repr_id(in): Representation identifier
3247  *
3248  *
3249  */
3250 static int
3251 catalog_drop (THREAD_ENTRY * thread_p, OID * class_id_p, REPR_ID repr_id)
3252 {
3253  CATALOG_REPR_ITEM repr_item;
3255  OID dir_oid;
3256  int error_code = NO_ERROR;
3257 
3258  repr_item.repr_id = repr_id;
3259  VPID_SET_NULL (&repr_item.page_id);
3260  repr_item.slot_id = NULL_SLOTID;
3261 
3262  error_code = catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid);
3263  if (error_code != NO_ERROR)
3264  {
3265  return error_code;
3266  }
3267 
3268  catalog_access_info.class_oid = class_id_p;
3269  catalog_access_info.dir_oid = &dir_oid;
3270  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
3271  if (error_code != NO_ERROR)
3272  {
3273  return error_code;
3274  }
3275 
3276  if ((catalog_drop_representation_item (thread_p, class_id_p, &repr_item) != NO_ERROR)
3277  || repr_item.page_id.pageid == NULL_PAGEID || repr_item.page_id.volid == NULL_VOLID
3278  || repr_item.slot_id == NULL_SLOTID)
3279  {
3280  ASSERT_ERROR_AND_SET (error_code);
3281  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3282  return error_code;
3283  }
3284 
3285  if (catalog_drop_disk_representation_from_page (thread_p, &repr_item.page_id, repr_item.slot_id) != NO_ERROR)
3286  {
3287  ASSERT_ERROR_AND_SET (error_code);
3288  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3289  return error_code;
3290  }
3291 
3292  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
3293 
3294  return NO_ERROR;
3295 }
3296 
3297 /*
3298  * catalog_drop_all () - Drop all representations for the class from the catalog
3299  * return: int
3300  * class_id(in): Class identifier
3301  *
3302  * Note: All the disk representations of the given class identifier are
3303  * dropped from the catalog.
3304  */
3305 static int
3306 catalog_drop_all (THREAD_ENTRY * thread_p, OID * class_id_p)
3307 {
3308  PAGE_PTR page_p;
3309  RECDES record;
3310  int i, repr_count;
3311  OID rep_dir;
3312  char *repr_p;
3313  REPR_ID repr_id;
3314  int error;
3315 
3316  OID_SET_NULL (&rep_dir); /* init */
3317 
3318  if (OID_ISTEMP (class_id_p))
3319  {
3320  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_INVALID_CLASSID, 3, class_id_p->volid, class_id_p->pageid,
3321  class_id_p->slotid);
3322  return ER_CT_INVALID_CLASSID;
3323  }
3324 
3326  {
3327  assert (er_errid () != NO_ERROR);
3328  return er_errid ();
3329  }
3330 
3331  page_p = catalog_get_representation_record_after_search (thread_p, class_id_p, &record, PGBUF_LATCH_READ, COPY,
3332  &rep_dir, &repr_count, true /* lookup_hash */ );
3333  if (page_p == NULL)
3334  {
3335  recdes_free_data_area (&record);
3336 
3337  assert (er_errid () != NO_ERROR);
3338  return er_errid ();
3339  }
3340 
3341  repr_p = record.data;
3342  pgbuf_unfix_and_init (thread_p, page_p);
3343 
3344  /* drop each representation one by one */
3345  for (i = 0; i < repr_count; i++, repr_p += CATALOG_REPR_ITEM_SIZE)
3346  {
3347  repr_id = CATALOG_GET_REPR_ITEM_REPRID (repr_p);
3348  if (repr_id == NULL_REPRID)
3349  {
3350  continue;
3351  }
3352 
3353  error = catalog_drop (thread_p, class_id_p, repr_id);
3354  if (error < 0)
3355  {
3356  recdes_free_data_area (&record);
3357  return error;
3358  }
3359  }
3360 
3361  recdes_free_data_area (&record);
3362  return NO_ERROR;
3363 }
3364 
3365 /*
3366  * catalog_drop_all_representation_and_class () -
3367  * return: NO_ERROR or ER_FAILED
3368  * class_id(in): Class identifier
3369  *
3370  * Note: All the disk representations of the given class identifier and
3371  * the class specific information of the class, if any, are
3372  * deleted from the catalog, as well as the class representations
3373  * directory and the index entry for the given class.
3374  * If there is no representation and class specific information
3375  * for the given class identifier, an error condition is raised.
3376  *
3377  * The catalog index is consulted to locate the class directory.
3378  * The class specific information and each representation
3379  * pointed to by the class directory is deleted from the catalog.
3380  */
3381 static int
3383 {
3384  PAGE_PTR page_p;
3385  PGLENGTH new_space;
3386  RECDES record;
3387  int i, repr_count;
3388  OID rep_dir;
3389  VPID vpid;
3390  char *repr_p;
3391  REPR_ID repr_id;
3392  VPID page_id;
3394  OID dir_oid;
3395  PGSLOTID slot_id;
3396  int error_code = NO_ERROR;
3397 
3398  OID_SET_NULL (&rep_dir); /* init */
3399 
3400  if (OID_ISTEMP (class_id_p))
3401  {
3402  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_INVALID_CLASSID, 3, class_id_p->volid, class_id_p->pageid,
3403  class_id_p->slotid);
3404  return ER_FAILED;
3405  }
3406 
3408  {
3409  return ER_FAILED;
3410  }
3411 
3412  error_code = catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid);
3413  if (error_code != NO_ERROR)
3414  {
3415  recdes_free_data_area (&record);
3416  return error_code;
3417  }
3418 
3419  catalog_access_info.class_oid = class_id_p;
3420  catalog_access_info.dir_oid = &dir_oid;
3421  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
3422  if (error_code != NO_ERROR)
3423  {
3424  recdes_free_data_area (&record);
3425  return error_code;
3426  }
3427 
3428  page_p = catalog_get_representation_record_after_search (thread_p, class_id_p, &record, PGBUF_LATCH_WRITE, COPY,
3429  &rep_dir, &repr_count, true /* lookup_hash */ );
3430  if (page_p == NULL)
3431  {
3432  recdes_free_data_area (&record);
3433  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3434  return ER_FAILED;
3435  }
3436 
3437  repr_p = record.data;
3438  vpid.volid = rep_dir.volid;
3439  vpid.pageid = rep_dir.pageid;
3440 
3441  /* drop each representation item one by one */
3442  for (i = 0; i < repr_count; i++, repr_p += CATALOG_REPR_ITEM_SIZE)
3443  {
3444  repr_id = CATALOG_GET_REPR_ITEM_REPRID (repr_p);
3445  page_id.pageid = CATALOG_GET_REPR_ITEM_PAGEID_PAGEID (repr_p);
3446  page_id.volid = CATALOG_GET_REPR_ITEM_PAGEID_VOLID (repr_p);
3447  slot_id = CATALOG_GET_REPR_ITEM_SLOTID (repr_p);
3448 
3449  catalog_delete_key (thread_p, class_id_p, repr_id);
3450 
3451  if (catalog_drop_representation_class_from_page (thread_p, &vpid, &page_p, &page_id, slot_id) != NO_ERROR)
3452  {
3453  if (page_p != NULL)
3454  {
3455  pgbuf_unfix_and_init (thread_p, page_p);
3456  }
3457  recdes_free_data_area (&record);
3458  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3459  return ER_FAILED;
3460  }
3461  assert (page_p != NULL);
3462  }
3463 
3464  if (catalog_drop_directory (thread_p, page_p, &record, &rep_dir, class_id_p) != NO_ERROR)
3465  {
3466  pgbuf_unfix_and_init (thread_p, page_p);
3467  recdes_free_data_area (&record);
3468  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3469  return ER_FAILED;
3470  }
3471 
3472  new_space = spage_max_space_for_new_record (thread_p, page_p);
3473  pgbuf_set_dirty (thread_p, page_p, FREE);
3474  catalog_update_max_space (&vpid, new_space);
3475  recdes_free_data_area (&record);
3476 
3477  catalog_delete_key (thread_p, class_id_p, CATALOG_DIR_REPR_KEY);
3478  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
3479 
3480  return NO_ERROR;
3481 }
3482 
3483 /*
3484  * catalog_drop_old_representations () -
3485  * return: NO_ERROR or ER_FAILED
3486  * class_id(in): Class identifier
3487  *
3488  * Note: All the disk representations of the given class identifier but
3489  * the most recent one are deleted from the catalog. if there is
3490  * no such class stored in the catalog, an error condition is raised.
3491  */
3492 int
3494 {
3495  PAGE_PTR page_p;
3496  PGLENGTH new_space;
3497  RECDES record;
3498  int i, repr_count;
3499  OID rep_dir;
3500  VPID vpid;
3501  char *repr_p, *last_repr_p;
3502  REPR_ID repr_id;
3503  VPID page_id;
3504  PGSLOTID slot_id;
3505  CATALOG_REPR_ITEM last_repr, class_repr;
3507  OID dir_oid;
3508  int is_any_dropped;
3509  bool error_code = NO_ERROR;
3510 
3511  OID_SET_NULL (&rep_dir); /* init */
3512 
3513  if (OID_ISTEMP (class_id_p))
3514  {
3515  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_INVALID_CLASSID, 3, class_id_p->volid, class_id_p->pageid,
3516  class_id_p->slotid);
3517  return ER_FAILED;
3518  }
3519 
3521  {
3522  return ER_FAILED;
3523  }
3524 
3525  error_code = catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid);
3526  if (error_code != NO_ERROR)
3527  {
3528  recdes_free_data_area (&record);
3529  return error_code;
3530  }
3531 
3532  catalog_access_info.class_oid = class_id_p;
3533  catalog_access_info.dir_oid = &dir_oid;
3534  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
3535  if (error_code != NO_ERROR)
3536  {
3537  recdes_free_data_area (&record);
3538  return error_code;
3539  }
3540 
3541  page_p = catalog_get_representation_record_after_search (thread_p, class_id_p, &record, PGBUF_LATCH_WRITE, COPY,
3542  &rep_dir, &repr_count, true /* lookup_hash */ );
3543  if (page_p == NULL)
3544  {
3545  recdes_free_data_area (&record);
3546  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3547  return ER_FAILED;
3548  }
3549 
3550  repr_p = record.data;
3551  vpid.volid = rep_dir.volid;
3552  vpid.pageid = rep_dir.pageid;
3553 
3554  VPID_SET_NULL (&last_repr.page_id);
3555  VPID_SET_NULL (&class_repr.page_id);
3556  class_repr.repr_id = NULL_REPRID;
3557  class_repr.slot_id = NULL_SLOTID;
3558 
3559  if (repr_count > 0)
3560  {
3561  last_repr_p = repr_p + ((repr_count - 1) * CATALOG_REPR_ITEM_SIZE);
3562  catalog_get_repr_item_from_record (&last_repr, last_repr_p);
3563 
3564  if (last_repr.repr_id == NULL_REPRID && repr_count > 1)
3565  {
3566  last_repr_p = repr_p + ((repr_count - 2) * CATALOG_REPR_ITEM_SIZE);
3567  catalog_get_repr_item_from_record (&last_repr, last_repr_p);
3568  }
3569  }
3570 
3571  is_any_dropped = false;
3572  for (i = 0; i < repr_count; i++, repr_p += CATALOG_REPR_ITEM_SIZE)
3573  {
3574  repr_id = CATALOG_GET_REPR_ITEM_REPRID (repr_p);
3575  page_id.pageid = CATALOG_GET_REPR_ITEM_PAGEID_PAGEID (repr_p);
3576  page_id.volid = CATALOG_GET_REPR_ITEM_PAGEID_VOLID (repr_p);
3577  slot_id = CATALOG_GET_REPR_ITEM_SLOTID (repr_p);
3578 
3579  if (repr_id != NULL_REPRID && repr_id != last_repr.repr_id)
3580  {
3581  catalog_delete_key (thread_p, class_id_p, repr_id);
3582 
3583  if (catalog_drop_representation_class_from_page (thread_p, &vpid, &page_p, &page_id, slot_id) != NO_ERROR)
3584  {
3585  if (page_p != NULL)
3586  {
3587  pgbuf_unfix_and_init (thread_p, page_p);
3588  }
3589  recdes_free_data_area (&record);
3590  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3591  return ER_FAILED;
3592  }
3593  assert (page_p != NULL);
3594 
3595  is_any_dropped = true;
3596  }
3597  else if (repr_id == NULL_REPRID)
3598  {
3599  class_repr.repr_id = repr_id;
3600  class_repr.page_id = page_id;
3601  class_repr.slot_id = slot_id;
3602  }
3603  }
3604 
3605  /* update the class directory itself, if needed */
3606  if (is_any_dropped)
3607  {
3608  log_append_undo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir.slotid, &record);
3609 
3610  if (class_repr.page_id.pageid != NULL_PAGEID)
3611  {
3612  /* first class info */
3613  catalog_put_repr_item_to_record (record.data, &class_repr);
3614  if (last_repr.page_id.pageid != NULL_PAGEID)
3615  {
3617  /* save #repr */
3619  }
3620  else
3621  {
3622  /* save #repr */
3624  }
3625  }
3626  else if (last_repr.page_id.pageid != NULL_PAGEID)
3627  {
3628  /* last repr item */
3629  catalog_put_repr_item_to_record (record.data, &last_repr);
3630  /* save #repr */
3632  }
3633  record.length = CATALOG_REPR_ITEM_SIZE * 2;
3634 
3635  if (spage_update (thread_p, page_p, rep_dir.slotid, &record) != SP_SUCCESS)
3636  {
3637  pgbuf_unfix_and_init (thread_p, page_p);
3638  recdes_free_data_area (&record);
3639  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
3640  return ER_FAILED;
3641  }
3642 
3643  log_append_redo_recdes2 (thread_p, RVCT_UPDATE, &catalog_Id.vfid, page_p, rep_dir.slotid, &record);
3644  }
3645 
3646  new_space = spage_max_space_for_new_record (thread_p, page_p);
3647  pgbuf_set_dirty (thread_p, page_p, FREE);
3648  catalog_update_max_space (&vpid, new_space);
3649 
3650  recdes_free_data_area (&record);
3651  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
3652  return NO_ERROR;
3653 }
3654 
3655 /*
3656  * xcatalog_check_rep_dir () -
3657  * return: NO_ERROR or ER_FAILED
3658  * class_id(in): Class identifier
3659  * rep_dir_p(out): Representation Directory
3660  *
3661  * Note: Get oid of class representation record
3662  */
3663 int
3664 xcatalog_check_rep_dir (THREAD_ENTRY * thread_p, OID * class_id_p, OID * rep_dir_p)
3665 {
3666  RECDES record;
3667  PAGE_PTR page_p;
3668  int repr_count;
3669 
3670  assert (rep_dir_p != NULL);
3671 
3672  OID_SET_NULL (rep_dir_p); /* init */
3673 
3674  record.area_size = -1;
3675 
3676  if (OID_ISTEMP (class_id_p))
3677  {
3678  assert (false); /* should avoid */
3679  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_INVALID_CLASSID, 3, class_id_p->volid, class_id_p->pageid,
3680  class_id_p->slotid);
3681  return ER_FAILED;
3682  }
3683 
3684  page_p = catalog_get_representation_record_after_search (thread_p, class_id_p, &record, PGBUF_LATCH_WRITE, PEEK,
3685  rep_dir_p, &repr_count, true /* lookup_hash */ );
3686 
3687  assert (er_errid () != ER_HEAP_NODATA_NEWADDRESS); /* TODO - */
3688 
3689  if (page_p == NULL)
3690  {
3691  return ER_FAILED;
3692  }
3693 
3694  pgbuf_unfix_and_init (thread_p, page_p);
3695 
3696  assert (repr_count == 1 || repr_count == 2);
3697 
3698  if (OID_ISNULL (rep_dir_p))
3699  {
3700  assert (false);
3701  return ER_FAILED;
3702  }
3703 
3704  return NO_ERROR;
3705 }
3706 
3707 #if defined (ENABLE_UNUSED_FUNCTION)
3708 /*
3709  * catalog_fixup_missing_disk_representation () -
3710  * return:
3711  * class_oid(in):
3712  * reprid(in):
3713  */
3714 static int
3715 catalog_fixup_missing_disk_representation (THREAD_ENTRY * thread_p, OID * class_oid_p, REPR_ID repr_id)
3716 {
3717  RECDES record;
3718  DISK_REPR *disk_repr_p;
3719  HEAP_SCANCACHE scan_cache;
3720  OID rep_dir = { NULL_PAGEID, NULL_SLOTID, NULL_VOLID };
3721  int ret = NO_ERROR;
3722 
3723  heap_scancache_quick_start_root_hfid (thread_p, &scan_cache);
3724  if (heap_get (thread_p, class_oid_p, &record, &scan_cache, PEEK, NULL_CHN) == S_SUCCESS)
3725  {
3726  disk_repr_p = orc_diskrep_from_record (thread_p, &record);
3727  if (disk_repr_p == NULL)
3728  {
3729  ASSERT_ERROR_AND_SET (ret);
3730  goto end;
3731  }
3732 
3733  or_class_rep_dir (&record, &rep_dir);
3734  assert (!OID_ISNULL (&rep_dir));
3735 
3736  if (catalog_add_representation (thread_p, class_oid_p, repr_id, disk_repr_p, &rep_dir) < 0)
3737  {
3738  ASSERT_ERROR_AND_SET (ret);
3739  orc_free_diskrep (disk_repr_p);
3740  goto end;
3741  }
3742  orc_free_diskrep (disk_repr_p);
3743  }
3744 
3745 end:
3746  heap_scancache_end (thread_p, &scan_cache);
3747  return ret;
3748 }
3749 #endif /* ENABLE_UNUSED_FUNCTION */
3750 
3751 /*
3752  * catalog_assign_attribute () -
3753  * return: NO_ERROR or ER_FAILED
3754  * disk_attrp(in): pointer to DISK_ATTR structure (disk representation)
3755  * catalog_record_p(in): pointer to CATALOG_RECORD structure (catalog record)
3756  */
3757 static int
3758 catalog_assign_attribute (THREAD_ENTRY * thread_p, DISK_ATTR * disk_attr_p, CATALOG_RECORD * catalog_record_p)
3759 {
3760  BTREE_STATS *btree_stats_p;
3761  int i, n_btstats;
3762 
3763  if (catalog_fetch_disk_attribute (thread_p, disk_attr_p, catalog_record_p) != NO_ERROR)
3764  {
3765  return ER_FAILED;
3766  }
3767 
3768  if (disk_attr_p->val_length > 0)
3769  {
3770  disk_attr_p->value = db_private_alloc (thread_p, disk_attr_p->val_length);
3771  if (disk_attr_p->value == NULL)
3772  {
3773  return ER_FAILED;
3774  }
3775  }
3776 
3777  if (catalog_fetch_attribute_value (thread_p, disk_attr_p->value, disk_attr_p->val_length, catalog_record_p) !=
3778  NO_ERROR)
3779  {
3780  return ER_FAILED;
3781  }
3782 
3783  n_btstats = disk_attr_p->n_btstats;
3784  if (n_btstats > 0)
3785  {
3786  disk_attr_p->bt_stats = (BTREE_STATS *) db_private_alloc (thread_p, (sizeof (BTREE_STATS) * n_btstats));
3787  if (disk_attr_p->bt_stats == NULL)
3788  {
3789  return ER_FAILED;
3790  }
3791  memset (disk_attr_p->bt_stats, 0, sizeof (BTREE_STATS) * n_btstats);
3792 
3793  /* init */
3794  for (i = 0; i < n_btstats; i++)
3795  {
3796  btree_stats_p = &disk_attr_p->bt_stats[i];
3797  btree_stats_p->pkeys = NULL;
3798  }
3799 
3800  /* fetch all B+tree index statistics of the attribute */
3801  for (i = 0; i < n_btstats; i++)
3802  {
3803  btree_stats_p = &disk_attr_p->bt_stats[i];
3804 
3805  if (catalog_fetch_btree_statistics (thread_p, btree_stats_p, catalog_record_p) != NO_ERROR)
3806  {
3807  return ER_FAILED;
3808  }
3809  }
3810  }
3811 
3812  return NO_ERROR;
3813 }
3814 
3815 /*
3816  * catalog_get_representation () - Get disk representation from the catalog
3817  * return: Pointer to the disk representation structure, or NULL.
3818  * class_id(in): Class identifier
3819  * repr_id(in): Disk Representation identifier
3820  * catalog_access_info_p(in): access info on catalog; if this is NULL
3821  * locking of directory OID is performed here,
3822  * otherwise the caller is reponsible for
3823  * protecting concurrent access.
3824  *
3825  * Note: The disk representation structure for the given class and
3826  * representation identifier is extracted from the catalog and
3827  * returned. If there is no representation with the given class
3828  * identifier and representation identifier, NULL is returned.
3829  * The memory area for the representation structure should be
3830  * freed explicitly by the caller, possibly by calling the
3831  * catalog_free_representation() routine.
3832  *
3833  * First, the memory hash table is consulted to get the location
3834  * of the representation in the catalog in terms of a page and a
3835  * slot identifier. If the memory hash table doesn't have this
3836  * information, then the catalog index is consulted to get the
3837  * location of the class representations directory in the catalog
3838  * The class directory is searched to locate the entry that
3839  * points to the specified disk representation in the catalog.
3840  * The location of the representation is recorded in the memory
3841  * hash table for further use. If the memory hash table becomes
3842  * full, it is cleared. The disk representation structure is
3843  * formed from the catalog page record and the overflow page
3844  * records, if any, and is returned.
3845  */
3846 DISK_REPR *
3847 catalog_get_representation (THREAD_ENTRY * thread_p, OID * class_id_p, REPR_ID repr_id,
3848  CATALOG_ACCESS_INFO * catalog_access_info_p)
3849 {
3850  CATALOG_REPR_ITEM repr_item;
3852  DISK_REPR *disk_repr_p = NULL;
3853  DISK_ATTR *disk_attr_p = NULL;
3855  OID dir_oid;
3856  int i;
3857  int error = NO_ERROR;
3858  bool do_end_access = false;
3859 
3860  catalog_record.page_p = NULL;
3861 
3862  if (catalog_access_info_p == NULL)
3863  {
3864  if (catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid) != NO_ERROR)
3865  {
3866  goto exit_on_error;
3867  }
3868 
3869  catalog_access_info.class_oid = class_id_p;
3870  catalog_access_info.dir_oid = &dir_oid;
3871  if (catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK) != NO_ERROR)
3872  {
3873  goto exit_on_error;
3874  }
3875  do_end_access = true;
3876  catalog_access_info_p = &catalog_access_info;
3877  }
3878 
3879  if (repr_id == NULL_REPRID)
3880  {
3882  if (do_end_access)
3883  {
3884  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3885  }
3886  return NULL;
3887  }
3888 
3889  repr_item.page_id.pageid = NULL_PAGEID;
3890  repr_item.page_id.volid = NULL_VOLID;
3891  repr_item.slot_id = NULL_SLOTID;
3892 
3893  assert (repr_id != NULL_REPRID);
3894  repr_item.repr_id = repr_id;
3895  if (catalog_get_representation_item (thread_p, class_id_p, &repr_item) != NO_ERROR)
3896  {
3897  if (do_end_access)
3898  {
3899  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3900  }
3901  return NULL;
3902  }
3903 
3904  catalog_record.vpid.pageid = repr_item.page_id.pageid;
3905  catalog_record.vpid.volid = repr_item.page_id.volid;
3906  catalog_record.slotid = repr_item.slot_id;
3907  catalog_record.page_p = NULL;
3908  catalog_record.recdes.length = 0;
3909  catalog_record.offset = 0;
3910 
3911  disk_repr_p = (DISK_REPR *) db_private_alloc (thread_p, sizeof (DISK_REPR));
3912  if (!disk_repr_p)
3913  {
3914  if (do_end_access)
3915  {
3916  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3917  }
3918  return NULL;
3919  }
3920  memset (disk_repr_p, 0, sizeof (DISK_REPR));
3921 
3922  if (catalog_fetch_disk_representation (thread_p, disk_repr_p, &catalog_record) != NO_ERROR)
3923  {
3924  if (disk_repr_p)
3925  {
3927  }
3928 
3929  if (catalog_record.page_p)
3930  {
3931  pgbuf_unfix_and_init (thread_p, catalog_record.page_p);
3932  }
3933 
3934  if (er_errid () == ER_SP_UNKNOWN_SLOTID)
3935  {
3936  assert (false);
3937  }
3938  if (do_end_access)
3939  {
3940  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
3941  }
3942  return NULL;
3943  }
3944 
3945  if (disk_repr_p->n_fixed > 0)
3946  {
3947  disk_repr_p->fixed = (DISK_ATTR *) db_private_alloc (thread_p, (sizeof (DISK_ATTR) * disk_repr_p->n_fixed));
3948  if (!disk_repr_p->fixed)
3949  {
3950  goto exit_on_error;
3951  }
3952  memset (disk_repr_p->fixed, 0, sizeof (DISK_ATTR) * disk_repr_p->n_fixed);
3953 
3954  /* init */
3955  for (i = 0; i < disk_repr_p->n_fixed; i++)
3956  {
3957  disk_attr_p = &disk_repr_p->fixed[i];
3958  disk_attr_p->value = NULL;
3959  disk_attr_p->bt_stats = NULL;
3960  disk_attr_p->n_btstats = 0;
3961  }
3962  }
3963  else
3964  {
3965  disk_repr_p->fixed = NULL;
3966  }
3967 
3968  if (disk_repr_p->n_variable > 0)
3969  {
3970  disk_repr_p->variable = (DISK_ATTR *) db_private_alloc (thread_p, (sizeof (DISK_ATTR) * disk_repr_p->n_variable));
3971  if (!disk_repr_p->variable)
3972  {
3973  goto exit_on_error;
3974  }
3975  memset (disk_repr_p->variable, 0, sizeof (DISK_ATTR) * disk_repr_p->n_variable);
3976 
3977  /* init */
3978  for (i = 0; i < disk_repr_p->n_variable; i++)
3979  {
3980  disk_attr_p = &disk_repr_p->variable[i];
3981  disk_attr_p->value = NULL;
3982  disk_attr_p->bt_stats = NULL;
3983  disk_attr_p->n_btstats = 0;
3984  }
3985  }
3986  else
3987  {
3988  disk_repr_p->variable = NULL;
3989  }
3990 
3991  for (i = 0; i < disk_repr_p->n_fixed; i++)
3992  {
3993  if (catalog_assign_attribute (thread_p, &disk_repr_p->fixed[i], &catalog_record) != NO_ERROR)
3994  {
3995  goto exit_on_error;
3996  }
3997  }
3998 
3999  for (i = 0; i < disk_repr_p->n_variable; i++)
4000  {
4001  if (catalog_assign_attribute (thread_p, &disk_repr_p->variable[i], &catalog_record) != NO_ERROR)
4002  {
4003  goto exit_on_error;
4004  }
4005  }
4006 
4007 exit_on_end:
4008 
4009  if (catalog_record.page_p)
4010  {
4011  pgbuf_unfix_and_init (thread_p, catalog_record.page_p);
4012  }
4013 
4014  if (do_end_access)
4015  {
4016  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, error);
4017  }
4018 
4019  return disk_repr_p;
4020 
4021 exit_on_error:
4022 
4023  error = ER_FAILED;
4024  if (disk_repr_p)
4025  {
4027  }
4028 
4029  goto exit_on_end;
4030 }
4031 
4032 #if defined (ENABLE_UNUSED_FUNCTION)
4033 static int
4034 catalog_fixup_missing_class_info (THREAD_ENTRY * thread_p, OID * class_oid_p)
4035 {
4036  RECDES record;
4037  HEAP_SCANCACHE scan_cache;
4038  CLS_INFO class_info = CLS_INFO_INITIALIZER;
4039 
4040  heap_scancache_quick_start_root_hfid (thread_p, &scan_cache);
4041 
4042  if (heap_get (thread_p, class_oid_p, &record, &scan_cache, PEEK, NULL_CHN) == S_SUCCESS)
4043  {
4044  or_class_hfid (&record, &(class_info.ci_hfid));
4045  or_class_rep_dir (&record, &(class_info.ci_rep_dir));
4046  assert (!OID_ISNULL (&(class_info.ci_rep_dir)));
4047 
4048  if (catalog_add_class_info (thread_p, class_oid_p, &class_info) < 0)
4049  {
4050  heap_scancache_end (thread_p, &scan_cache);
4051 
4052  assert (er_errid () != NO_ERROR);
4053  return er_errid ();
4054  }
4055  }
4056 
4057  heap_scancache_end (thread_p, &scan_cache);
4058 
4059  return NO_ERROR;
4060 }
4061 #endif /* ENABLE_UNUSED_FUNCTION */
4062 
4063 /*
4064  * catalog_get_class_info () - Get class information from the catalog
4065  * return: Pointer to the class information structure, or NULL.
4066  * class_id_p(in): Class identifier
4067  * catalog_access_info_p(in): access info on catalog; if this is NULL
4068  * locking of directory OID is performed here,
4069  * otherwise the caller is reponsible for
4070  * protecting concurrent access.
4071  *
4072  * Note: The class information structure for the given class is
4073  * extracted from the catalog and returned. If there is no class
4074  * in the catalog with the given class identifier, NULL is returned.
4075  *
4076  * First, the memory hash table is consulted to get the location
4077  * of the class information in the catalog in terms of a page
4078  * and a slot identifier. If the memory hash table doesn't have
4079  * this information, then the catalog index is consulted to get
4080  * location of the class representations directory in the catalog
4081  * The class directory is searched to locate the entry that
4082  * points to the specified class information in the catalog. The
4083  * ocation of the class information is recorded in the memory
4084  * hash table for further use. If the memory hash table becomes
4085  * full, it is cleared. The class information structure is formed
4086  * from the catalog page record and is returned.
4087  */
4088 CLS_INFO *
4089 catalog_get_class_info (THREAD_ENTRY * thread_p, OID * class_id_p, CATALOG_ACCESS_INFO * catalog_access_info_p)
4090 {
4091  CLS_INFO *class_info_p = NULL;
4092  PAGE_PTR page_p;
4093  char data[CATALOG_CLS_INFO_SIZE + MAX_ALIGNMENT], *aligned_data;
4097  OID dir_oid;
4098 #if 0
4099  int retry = 0;
4100 #endif
4101  bool do_end_access = false;
4102 
4103  aligned_data = PTR_ALIGN (data, MAX_ALIGNMENT);
4104 
4105 #if 0
4106 start:
4107 #endif
4108 
4109  if (catalog_access_info_p == NULL)
4110  {
4111  if (catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid) != NO_ERROR)
4112  {
4113  return NULL;
4114  }
4115 
4116  catalog_access_info.class_oid = class_id_p;
4117  catalog_access_info.dir_oid = &dir_oid;
4118  if (catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK) != NO_ERROR)
4119  {
4120  return NULL;
4121  }
4122  do_end_access = true;
4123  catalog_access_info_p = &catalog_access_info;
4124  }
4125 
4126  assert (repr_item.repr_id == NULL_REPRID);
4127  repr_item.repr_id = NULL_REPRID;
4128  if (catalog_get_representation_item (thread_p, class_id_p, &repr_item) != NO_ERROR)
4129  {
4130  if (do_end_access)
4131  {
4132  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
4133  }
4134  return NULL;
4135  }
4136 
4137  page_p = pgbuf_fix (thread_p, &repr_item.page_id, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
4138  if (page_p == NULL)
4139  {
4140  if (do_end_access)
4141  {
4142  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
4143  }
4144  return NULL;
4145  }
4146 
4147  (void) pgbuf_check_page_ptype (thread_p, page_p, PAGE_CATALOG);
4148 
4149  recdes_set_data_area (&record, aligned_data, CATALOG_CLS_INFO_SIZE);
4150  if (spage_get_record (thread_p, page_p, repr_item.slot_id, &record, COPY) != S_SUCCESS)
4151  {
4152 #if defined(CT_DEBUG)
4153  if (er_errid () == ER_SP_UNKNOWN_SLOTID)
4154  {
4155  /* If this case happens, means, catalog doesn't contain a page slot which is referred to by index. It is
4156  * possible that the slot has been deleted from the catalog page, but necessary changes have not been
4157  * reflected to the index or to the memory hash table. */
4158  er_log_debug (ARG_FILE_LINE, "catalog_get_class_info: ",
4159  "no class information record found in catalog.\n"
4160  "possibly catalog index points to a non_existent disk repr.\n");
4161  }
4162 #endif /* CT_DEBUG */
4163 
4164  if (er_errid () == ER_SP_UNKNOWN_SLOTID)
4165  {
4166  assert (false);
4167 #if 0
4168  pgbuf_unfix_and_init (thread_p, page_p);
4169 
4170  if ((catalog_fixup_missing_class_info (thread_p, class_id_p) == NO_ERROR) && retry++ == 0)
4171  {
4172  goto start;
4173  }
4174  else
4175  {
4176  assert (0);
4177  return NULL;
4178  }
4179 #endif
4180  }
4181 
4182  pgbuf_unfix_and_init (thread_p, page_p);
4183  if (do_end_access)
4184  {
4185  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
4186  }
4187  return NULL;
4188  }
4189 
4190  class_info_p = (CLS_INFO *) db_private_alloc (thread_p, sizeof (CLS_INFO));
4191  if (class_info_p == NULL)
4192  {
4193  pgbuf_unfix_and_init (thread_p, page_p);
4194  if (do_end_access)
4195  {
4196  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, ER_FAILED);
4197  }
4198  return NULL;
4199  }
4200 
4201  catalog_get_class_info_from_record (class_info_p, record.data);
4202 
4203  pgbuf_unfix_and_init (thread_p, page_p);
4204 
4205  if (do_end_access)
4206  {
4207  catalog_end_access_with_dir_oid (thread_p, catalog_access_info_p, NO_ERROR);
4208  }
4209 
4210  assert (!OID_ISNULL (&(class_info_p->ci_rep_dir)));
4211 
4212  return class_info_p;
4213 }
4214 
4215 /*
4216  * catalog_get_representation_directory () - Get class representations directory
4217  * return: int
4218  * class_id(in): Class identifier
4219  * reprid_set(out): Set to the set of representation identifiers for the class
4220  * repr_cnt(out): Set to the representation count
4221  *
4222  * Note: The set of representation identifiers for the specified class
4223  * is extracted from the catalog and returned in the memory area
4224  * allocated in this routine and pointed to by reprid_set. The
4225  * variable repr_cnt is set to the number of identifiers in this
4226  * set. The representation identifiers are in a chronological
4227  * order of sequence, the first one representing the oldest and
4228  * last one representing the most recent representation for the given class.
4229  */
4230 int
4231 catalog_get_representation_directory (THREAD_ENTRY * thread_p, OID * class_id_p, REPR_ID ** repr_id_set_p,
4232  int *repr_count_p)
4233 {
4234  OID rep_dir;
4235  PAGE_PTR page_p;
4236  RECDES record;
4237  int i, item_count;
4238  char *repr_p;
4239  REPR_ID *repr_set_p;
4240  size_t buf_size;
4241 
4242  OID_SET_NULL (&rep_dir); /* init */
4243 
4244  *repr_count_p = 0;
4245 
4246  page_p = catalog_get_representation_record_after_search (thread_p, class_id_p, &record, PGBUF_LATCH_READ, PEEK,
4247  &rep_dir, &item_count, true /* lookup_hash */ );
4248  if (page_p == NULL)
4249  {
4250  assert (er_errid () != NO_ERROR);
4251  return er_errid ();
4252  }
4253 
4254  *repr_count_p = item_count;
4255  buf_size = *repr_count_p * sizeof (REPR_ID);
4256  *repr_id_set_p = (REPR_ID *) malloc (buf_size);
4257  if (*repr_id_set_p == NULL)
4258  {
4259  pgbuf_unfix_and_init (thread_p, page_p);
4260 
4262  return ER_OUT_OF_VIRTUAL_MEMORY;
4263  }
4264 
4265  repr_set_p = *repr_id_set_p;
4266 
4267  for (i = 0, repr_p = record.data; i < item_count; i++, repr_p += CATALOG_REPR_ITEM_SIZE)
4268  {
4269  if (CATALOG_GET_REPR_ITEM_REPRID (repr_p) == NULL_REPRID)
4270  {
4271  (*repr_count_p)--;
4272  }
4273  else
4274  {
4275  *repr_set_p = CATALOG_GET_REPR_ITEM_REPRID (repr_p);
4276  repr_set_p++;
4277  }
4278  }
4279 
4280  pgbuf_unfix_and_init (thread_p, page_p);
4281  return NO_ERROR;
4282 }
4283 
4284 /*
4285  * catalog_get_last_representation_id () -
4286  * return: int
4287  * cls_oid(in): Class identifier
4288  * repr_id(out): Set to the last representation id or NULL_REPRID
4289  *
4290  * Note: The representation identifiers directory for the given class
4291  * is fetched from the catalog and the repr_id parameter is set
4292  * to the most recent representation identifier, or NULL_REPRID.
4293  */
4294 int
4295 catalog_get_last_representation_id (THREAD_ENTRY * thread_p, OID * class_oid_p, REPR_ID * repr_id_p)
4296 {
4297  OID rep_dir;
4298  PAGE_PTR page_p;
4299  RECDES record;
4300  int i, item_count;
4301  char *repr_p;
4302 
4303  OID_SET_NULL (&rep_dir); /* init */
4304 
4305  *repr_id_p = NULL_REPRID;
4306 
4307  page_p = catalog_get_representation_record_after_search (thread_p, class_oid_p, &record, PGBUF_LATCH_READ, PEEK,
4308  &rep_dir, &item_count, true /* lookup_hash */ );
4309  if (page_p == NULL)
4310  {
4311  assert (er_errid () != NO_ERROR);
4312  return er_errid ();
4313  }
4314 
4315  for (i = 0, repr_p = record.data; i < item_count; i++, repr_p += CATALOG_REPR_ITEM_SIZE)
4316  {
4317  if (CATALOG_GET_REPR_ITEM_REPRID (repr_p) != NULL_REPRID)
4318  {
4319  *repr_id_p = CATALOG_GET_REPR_ITEM_REPRID (repr_p);
4320  }
4321  }
4322 
4323  pgbuf_unfix_and_init (thread_p, page_p);
4324  return NO_ERROR;
4325 }
4326 
4327 /*
4328  * catalog_insert () - Insert class representation information to catalog
4329  * return: int
4330  * record(in): Record descriptor containing class disk representation info.
4331  * classoid(in): Class object identifier
4332  * rep_dir_p(out): Representation Directory
4333  *
4334  * Note: The disk representation information for the initial
4335  * representation of the class and the class specific information
4336  * is extracted from the record descriptor and stored in the
4337  * catalog. This routine must be the first routine called for the
4338  * storage of class representation informations in the catalog.
4339  */
4340 int
4341 catalog_insert (THREAD_ENTRY * thread_p, RECDES * record_p, OID * class_oid_p, OID * rep_dir_p)
4342 {
4343  REPR_ID new_repr_id;
4344  DISK_REPR *disk_repr_p = NULL;
4345  CLS_INFO *class_info_p = NULL;
4346 
4347  assert (class_oid_p != NULL);
4348  assert (record_p != NULL);
4349  assert (rep_dir_p != NULL);
4350  assert (OID_ISNULL (rep_dir_p));
4351 
4352  new_repr_id = (REPR_ID) or_rep_id (record_p);
4353  if (new_repr_id == NULL_REPRID)
4354  {
4356  return ER_CT_INVALID_REPRID;
4357  }
4358 
4359  disk_repr_p = orc_diskrep_from_record (thread_p, record_p);
4360  if (disk_repr_p == NULL)
4361  {
4362  assert (er_errid () != NO_ERROR);
4363  return er_errid ();
4364  }
4365 
4366  assert (OID_ISNULL (rep_dir_p));
4367  if (catalog_add_representation (thread_p, class_oid_p, new_repr_id, disk_repr_p, rep_dir_p, NULL) < 0
4368  || OID_ISNULL (rep_dir_p))
4369  {
4370  orc_free_diskrep (disk_repr_p);
4371 
4372  assert (er_errid () != NO_ERROR);
4373  return er_errid ();
4374  }
4375 
4376  assert (!OID_ISNULL (rep_dir_p));
4377 
4378  orc_free_diskrep (disk_repr_p);
4379 
4380  class_info_p = orc_class_info_from_record (record_p);
4381  if (class_info_p == NULL)
4382  {
4383  assert (er_errid () != NO_ERROR);
4384  return er_errid ();
4385  }
4386 
4387  /* save representation directory oid into class_info record */
4388  assert (OID_ISNULL (&(class_info_p->ci_rep_dir)));
4389  COPY_OID (&(class_info_p->ci_rep_dir), rep_dir_p);
4390 
4391  if (catalog_add_class_info (thread_p, class_oid_p, class_info_p, NULL) < 0)
4392  {
4393  orc_free_class_info (class_info_p);
4394 
4395  assert (er_errid () != NO_ERROR);
4396  return er_errid ();
4397  }
4398  orc_free_class_info (class_info_p);
4399 
4400  return NO_ERROR;
4401 }
4402 
4403 /*
4404  * catalog_update () - Update class representation information to catalog
4405  * return: int
4406  * record(in): Record descriptor containing class disk representation info.
4407  * classoid(in): Class object identifier
4408  *
4409  * Note: The disk representation information for the specified class and
4410  * also possibly the class specific information is updated, if
4411  * the record descriptor contains a new disk representation, ie.
4412  * has a new representation identifier different from the most
4413  * recent representation identifier of the class. The class
4414  * information is extracted and only the HFID field is set, if
4415  * needed, in order to preserve old class statistics.
4416  */
4417 int
4418 catalog_update (THREAD_ENTRY * thread_p, RECDES * record_p, OID * class_oid_p)
4419 {
4420  REPR_ID current_repr_id, new_repr_id;
4421  DISK_REPR *disk_repr_p = NULL;
4422  DISK_REPR *old_repr_p = NULL;
4423  CLS_INFO *class_info_p = NULL;
4424  OID rep_dir;
4425  int err;
4426 
4427  new_repr_id = (REPR_ID) or_rep_id (record_p);
4428  if (new_repr_id == NULL_REPRID)
4429  {
4431  return ER_CT_INVALID_REPRID;
4432  }
4433 
4434  or_class_rep_dir (record_p, &rep_dir);
4435  assert (!OID_ISNULL (&rep_dir));
4436 
4437  disk_repr_p = orc_diskrep_from_record (thread_p, record_p);
4438  if (disk_repr_p == NULL)
4439  {
4440  assert (er_errid () != NO_ERROR);
4441  return er_errid ();
4442  }
4443 
4444  if (catalog_get_last_representation_id (thread_p, class_oid_p, &current_repr_id) < 0)
4445  {
4446  assert (er_errid () != NO_ERROR);
4447  return er_errid ();
4448  }
4449 
4450  if (current_repr_id != NULL_REPRID)
4451  {
4452  old_repr_p = catalog_get_representation (thread_p, class_oid_p, current_repr_id, NULL);
4453  if (old_repr_p == NULL)
4454  {
4455  if (er_errid () != ER_SP_UNKNOWN_SLOTID)
4456  {
4457  orc_free_diskrep (disk_repr_p);
4458 
4459  assert (er_errid () != NO_ERROR);
4460  return er_errid ();
4461  }
4462  }
4463 
4464  /* Migrate statistics from the old representation to the new one */
4465  if (old_repr_p)
4466  {
4467  catalog_copy_disk_attributes (disk_repr_p->fixed, disk_repr_p->n_fixed, old_repr_p->fixed,
4468  old_repr_p->n_fixed);
4469  catalog_copy_disk_attributes (disk_repr_p->variable, disk_repr_p->n_variable, old_repr_p->variable,
4470  old_repr_p->n_variable);
4471 
4473  err = catalog_drop (thread_p, class_oid_p, current_repr_id);
4474  if (err != NO_ERROR)
4475  {
4476  orc_free_diskrep (disk_repr_p);
4477  return err;
4478  }
4479  }
4480  }
4481 
4482  assert (!OID_ISNULL (&rep_dir));
4483  if (catalog_add_representation (thread_p, class_oid_p, new_repr_id, disk_repr_p, &rep_dir, NULL) < 0)
4484  {
4485  orc_free_diskrep (disk_repr_p);
4486 
4487  assert (er_errid () != NO_ERROR);
4488  return er_errid ();
4489  }
4490 
4491  orc_free_diskrep (disk_repr_p);
4492 
4493  class_info_p = catalog_get_class_info (thread_p, class_oid_p, NULL);
4494  if (class_info_p == NULL)
4495  {
4496  assert (er_errid () != NO_ERROR);
4497  return er_errid ();
4498  }
4499 
4500  assert (OID_EQ (&rep_dir, &(class_info_p->ci_rep_dir)));
4501 
4502  if (HFID_IS_NULL (&class_info_p->ci_hfid))
4503  {
4504  or_class_hfid (record_p, &(class_info_p->ci_hfid));
4505  if (!HFID_IS_NULL (&class_info_p->ci_hfid))
4506  {
4507  if (catalog_update_class_info (thread_p, class_oid_p, class_info_p, NULL, false) == NULL)
4508  {
4509  catalog_free_class_info (class_info_p);
4510 
4511  assert (er_errid () != NO_ERROR);
4512  return er_errid ();
4513  }
4514  }
4515  }
4516  catalog_free_class_info (class_info_p);
4517 
4518  return NO_ERROR;
4519 }
4520 
4521 /*
4522  * catalog_delete () - Delete class representation information from catalog
4523  * return: int
4524  * classoid(in): Class object identifier
4525  *
4526  * Note: All the disk representation information for the class and the
4527  * class specific information are dropped from the catalog.
4528  */
4529 int
4530 catalog_delete (THREAD_ENTRY * thread_p, OID * class_oid_p)
4531 {
4532  if (catalog_drop_all_representation_and_class (thread_p, class_oid_p) != NO_ERROR)
4533  {
4534  assert (er_errid () != NO_ERROR);
4535  return er_errid ();
4536  }
4537 
4538  return NO_ERROR;
4539 }
4540 
4541 /*
4542  * Checkdb consistency check routines
4543  */
4544 
4545 /*
4546  * catalog_check_class_consistency () -
4547  * return: DISK_VALID, DISK_INVALID or DISK_ERROR
4548  * class_oid_p(in): Class object identifier
4549  *
4550  * Note: This function checks the consistency of the class information
4551  * in the class and returns the consistency result. It checks
4552  * if the class points a valid page entry that
4553  * contains the representations directory for the class. It then
4554  * checks for each entry in the representations directory if
4555  * corresponding page slot entry exits.
4556  */
4557 static DISK_ISVALID
4559 {
4560  OID rep_dir;
4561  RECDES record;
4562  CATALOG_REPR_ITEM repr_item;
4563  VPID vpid;
4564  PAGE_PTR page_p;
4565  PAGE_PTR repr_page_p;
4566  int repr_count;
4567  char *repr_p;
4568  CLS_INFO class_info = CLS_INFO_INITIALIZER;
4569  int i;
4570  DISK_ISVALID valid;
4571 
4572  OID_SET_NULL (&rep_dir); /* init */
4573 
4574  record.area_size = -1;
4575 
4576  /* get old directory for the class */
4577  if (catalog_get_rep_dir (thread_p, class_oid_p, &rep_dir, true /* lookup_hash */ ) != NO_ERROR
4578  || OID_ISNULL (&rep_dir))
4579  {
4580  assert (er_errid () != NO_ERROR);
4581  return DISK_ERROR;
4582  }
4583 
4584  /* Check if the catalog index points to an existing representations directory. */
4585 
4586  vpid.volid = rep_dir.volid;
4587  vpid.pageid = rep_dir.pageid;
4588  valid = file_check_vpid (thread_p, &catalog_Id.vfid, &vpid);
4589 
4590  if (valid != DISK_VALID)
4591  {
4592  if (er_errid () == ER_PB_BAD_PAGEID)
4593  {
4595  rep_dir.slotid);
4596  }
4597 
4598  return valid;
4599  }
4600 
4601  page_p = catalog_get_representation_record (thread_p, &rep_dir, &record, PGBUF_LATCH_READ, PEEK, &repr_count);
4602 
4603  if (page_p == NULL)
4604  {
4605  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_MISSING_REPR_DIR, 3, class_oid_p->volid, class_oid_p->pageid,
4606  class_oid_p->slotid);
4607  return DISK_ERROR;
4608  }
4609 
4610  for (i = 0, repr_p = record.data; i < repr_count; i++, repr_p += CATALOG_REPR_ITEM_SIZE)
4611  {
4612  repr_item.page_id.pageid = CATALOG_GET_REPR_ITEM_PAGEID_PAGEID (repr_p);
4613  repr_item.page_id.volid = CATALOG_GET_REPR_ITEM_PAGEID_VOLID (repr_p);
4614  repr_item.slot_id = CATALOG_GET_REPR_ITEM_SLOTID (repr_p);
4615  repr_item.repr_id = CATALOG_GET_REPR_ITEM_REPRID (repr_p);
4616 
4617  valid = file_check_vpid (thread_p, &catalog_Id.vfid, &repr_item.page_id);
4618  if (valid != DISK_VALID)
4619  {
4620  pgbuf_unfix_and_init (thread_p, page_p);
4621  return valid;
4622  }
4623 
4624  repr_page_p = pgbuf_fix (thread_p, &repr_item.page_id, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
4625  if (repr_page_p == NULL)
4626  {
4627  pgbuf_unfix_and_init (thread_p, page_p);
4628  return DISK_ERROR;
4629  }
4630 
4631  (void) pgbuf_check_page_ptype (thread_p, repr_page_p, PAGE_CATALOG);
4632 
4633  if (spage_get_record (thread_p, repr_page_p, repr_item.slot_id, &record, PEEK) != S_SUCCESS)
4634  {
4635  pgbuf_unfix_and_init (thread_p, repr_page_p);
4636  pgbuf_unfix_and_init (thread_p, page_p);
4637  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CT_MISSING_REPR_INFO, 4, class_oid_p->volid, class_oid_p->pageid,
4638  class_oid_p->slotid, repr_item.repr_id);
4639  return DISK_ERROR;
4640  }
4641 
4642  /* is class info record */
4643  if (repr_item.repr_id == NULL_REPRID)
4644  {
4645  catalog_get_class_info_from_record (&class_info, record.data);
4646 
4647  if (!OID_EQ (&rep_dir, &(class_info.ci_rep_dir)))
4648  {
4649  assert (false);
4650  pgbuf_unfix_and_init (thread_p, repr_page_p);
4651  pgbuf_unfix_and_init (thread_p, page_p);
4653  class_oid_p->pageid, class_oid_p->slotid);
4654  return DISK_ERROR;
4655  }
4656  }
4657 
4658  pgbuf_unfix_and_init (thread_p, repr_page_p);
4659  }
4660 
4661  pgbuf_unfix_and_init (thread_p, page_p);
4662  return DISK_VALID;
4663 }
4664 
4665 /*
4666  * catalog_check_consistency () - Check if catalog is in a consistent (valid)
4667  * state.
4668  * return: DISK_VALID, DISK_INVALID or DISK_ERROR
4669  */
4672 {
4673  DISK_ISVALID ct_valid = DISK_VALID;
4674  RECDES peek = RECDES_INITIALIZER; /* Record descriptor for peeking object */
4675  HFID root_hfid;
4676  OID class_oid;
4677 #if !defined(NDEBUG)
4678  char *classname = NULL;
4679 #endif
4680  HEAP_SCANCACHE scan_cache;
4682 
4683  mvcc_snapshot = logtb_get_mvcc_snapshot (thread_p);
4684  if (mvcc_snapshot == NULL)
4685  {
4686  return DISK_ERROR;
4687  }
4688 
4689  /* Find every single class */
4690 
4691  if (boot_find_root_heap (&root_hfid) != NO_ERROR || HFID_IS_NULL (&root_hfid))
4692  {
4693  goto exit_on_error;
4694  }
4695 
4696  if (heap_scancache_start (thread_p, &scan_cache, &root_hfid, oid_Root_class_oid, true, false, mvcc_snapshot) !=
4697  NO_ERROR)
4698  {
4699  goto exit_on_error;
4700  }
4701 
4702  class_oid.volid = root_hfid.vfid.volid;
4703  class_oid.pageid = NULL_PAGEID;
4704  class_oid.slotid = NULL_SLOTID;
4705 
4706  ct_valid = DISK_VALID;
4707 
4708  while (heap_next (thread_p, &root_hfid, oid_Root_class_oid, &class_oid, &peek, &scan_cache, PEEK) == S_SUCCESS)
4709  {
4710 #if !defined(NDEBUG)
4711  classname = or_class_name (&peek);
4712  assert (classname != NULL);
4713  assert (strlen (classname) < 255);
4714 #endif
4715  if (lock_object (thread_p, &class_oid, oid_Root_class_oid, SCH_S_LOCK, LK_COND_LOCK) != LK_GRANTED)
4716  {
4717  /* we do the checks by best-effort. we need the lock to avoid all kind of inconsistencies from doing checks on
4718  * incomplete changes. doing an unconditional lock here is too complicated and unnecessary, since it is
4719  * unusual to do checkdb and schema changes concurrently. */
4721  "Skipping checking catalog for class %d|%d|%d because conditional lock failed. \n",
4722  OID_AS_ARGS (&class_oid));
4723  continue;
4724  }
4725  /* check catalog consistency */
4726  ct_valid = catalog_check_class_consistency (thread_p, &class_oid);
4727  /* remove lock */
4728  lock_unlock_object (thread_p, &class_oid, oid_Root_class_oid, SCH_S_LOCK, true);
4729  if (ct_valid != DISK_VALID)
4730  {
4731  break;
4732  }
4733  } /* while (...) */
4734 
4735  /* End the scan cursor */
4736  if (heap_scancache_end (thread_p, &scan_cache) != NO_ERROR)
4737  {
4738  ct_valid = DISK_ERROR;
4739  }
4740 
4741  return ct_valid;
4742 
4743 exit_on_error:
4744 
4745  return DISK_ERROR;
4746 }
4747 
4748 /*
4749  * catalog_dump_disk_attribute () -
4750  * return:
4751  * atr(in):
4752  */
4753 static void
4755 {
4756  char *value_p;
4757  int i, k;
4758  const char *prefix = "";
4759 
4760  fprintf (stdout, "\n");
4761  fprintf (stdout, "Attribute Information: \n\n ");
4762  fprintf (stdout, "Id: %d \n", attr_p->id);
4763  fprintf (stdout, " Type: ");
4764 
4765  switch (attr_p->type)
4766  {
4767  case DB_TYPE_INTEGER:
4768  fprintf (stdout, "DB_TYPE_INTEGER \n");
4769  break;
4770  case DB_TYPE_BIGINT:
4771  fprintf (stdout, "DB_TYPE_BIGINT \n");
4772  break;
4773  case DB_TYPE_FLOAT:
4774  fprintf (stdout, "DB_TYPE_FLOAT \n");
4775  break;
4776  case DB_TYPE_DOUBLE:
4777  fprintf (stdout, "DB_TYPE_DOUBLE \n");
4778  break;
4779  case DB_TYPE_STRING:
4780  fprintf (stdout, "DB_TYPE_STRING \n");
4781  break;
4782  case DB_TYPE_OBJECT:
4783  fprintf (stdout, "DB_TYPE_OBJECT \n");
4784  break;
4785  case DB_TYPE_SET:
4786  fprintf (stdout, "DB_TYPE_SET \n");
4787  break;
4788  case DB_TYPE_MULTISET:
4789  fprintf (stdout, "DB_TYPE_MULTISET \n");
4790  break;
4791  case DB_TYPE_SEQUENCE:
4792  fprintf (stdout, "DB_TYPE_SEQUENCE \n");
4793  break;
4794  case DB_TYPE_TIME:
4795  fprintf (stdout, "DB_TYPE_TIME \n");
4796  break;
4797  case DB_TYPE_MONETARY:
4798  fprintf (stdout, "DB_TYPE_MONETARY \n");
4799  break;
4800  case DB_TYPE_DATE:
4801  fprintf (stdout, "DB_TYPE_DATE \n");
4802  break;
4803  case DB_TYPE_BLOB:
4804  fprintf (stdout, "DB_TYPE_BLOB \n");
4805  break;
4806  case DB_TYPE_CLOB:
4807  fprintf (stdout, "DB_TYPE_CLOB \n");
4808  break;
4809  case DB_TYPE_VARIABLE:
4810  fprintf (stdout, "DB_TYPE_VARIABLE \n");
4811  break;
4812  case DB_TYPE_SUB:
4813  fprintf (stdout, "DB_TYPE_SUB \n");
4814  break;
4815  case DB_TYPE_POINTER:
4816  fprintf (stdout, "DB_TYPE_POINTER \n");
4817  break;
4818  case DB_TYPE_NULL:
4819  fprintf (stdout, "DB_TYPE_NULL \n");
4820  break;
4821  case DB_TYPE_JSON:
4822  fprintf (stdout, "DB_TYPE_JSON \n");
4823  break;
4824  default:
4825  break;
4826  }
4827 
4828  fprintf (stdout, " Location: %d \n", attr_p->location);
4829  fprintf (stdout, " Source Class_Id: { %d , %d , %d } \n", attr_p->classoid.volid, attr_p->classoid.pageid,
4830  attr_p->classoid.slotid);
4831  fprintf (stdout, " Source Position: %d \n", attr_p->position);
4832  fprintf (stdout, " Def. Value Length: %d \n", attr_p->val_length);
4833 
4834  if (attr_p->val_length > 0)
4835  {
4836  value_p = (char *) attr_p->value;
4837  fprintf (stdout, " Value: ");
4838 
4839  for (k = 0; k < attr_p->val_length; k++, value_p++)
4840  {
4841  fprintf (stdout, "%02X ", (unsigned char) (*value_p));
4842  }
4843  fprintf (stdout, " \n");
4844  }
4845 
4846  fprintf (stdout, " BTree statistics:\n");
4847 
4848  for (k = 0; k < attr_p->n_btstats; k++)
4849  {
4850  BTREE_STATS *bt_statsp = &attr_p->bt_stats[k];
4851  fprintf (stdout, " BTID: { %d , %d }\n", bt_statsp->btid.vfid.volid, bt_statsp->btid.vfid.fileid);
4852  fprintf (stdout, " Cardinality: %d (", bt_statsp->keys);
4853 
4854  prefix = "";
4855  assert (bt_statsp->pkeys_size <= BTREE_STATS_PKEYS_NUM);
4856  for (i = 0; i < bt_statsp->pkeys_size; i++)
4857  {
4858  fprintf (stdout, "%s%d", prefix, bt_statsp->pkeys[i]);
4859  prefix = ",";
4860  }
4861 
4862  fprintf (stdout, ") ,");
4863  fprintf (stdout, " Total Pages: %d , Leaf Pages: %d , Height: %d\n", bt_statsp->pages, bt_statsp->leafs,
4864  bt_statsp->height);
4865  }
4866 
4867  fprintf (stdout, "\n");
4868 }
4869 
4870 /*
4871  * catalog_dump_representation () -
4872  * return:
4873  * dr(in):
4874  */
4875 static void
4877 {
4878  DISK_ATTR *attr_p;
4879  int i;
4880 
4881  if (disk_repr_p != NULL)
4882  {
4883  fprintf (stdout, " DISK REPRESENTATION: \n\n");
4884  fprintf (stdout, " Repr_Id : %d N_Fixed : %d Fixed_Length : %d N_Variable : %d\n\n", disk_repr_p->id,
4885  disk_repr_p->n_fixed, disk_repr_p->fixed_length, disk_repr_p->n_variable);
4886 
4887  fprintf (stdout, " Fixed Attribute Representations : \n\n");
4888  attr_p = disk_repr_p->fixed;
4889  for (i = 0; i < disk_repr_p->n_fixed; i++, attr_p++)
4890  {
4891  catalog_dump_disk_attribute (attr_p);
4892  }
4893 
4894  fprintf (stdout, " Variable Attribute Representations : \n\n");
4895  attr_p = disk_repr_p->variable;
4896  for (i = 0; i < disk_repr_p->n_variable; i++, attr_p++)
4897  {
4898  catalog_dump_disk_attribute (attr_p);
4899  }
4900  }
4901 }
4902 
4903 /*
4904  * catalog_file_map_page_dump () - FILE_MAP_PAGE_FUNC for catalog page dump
4905  *
4906  * return : error code
4907  * thread_p (in) : thread entry
4908  * page (in) : catalog page pointer
4909  * stop (in) : not used
4910  * args (in) : FILE *
4911  */
4912 static int
4913 catalog_file_map_page_dump (THREAD_ENTRY * thread_p, PAGE_PTR * page, bool * stop, void *args)
4914 {
4916  RECDES record;
4917 
4918  if (spage_get_record (thread_p, *page, CATALOG_HEADER_SLOT, &record, PEEK) != S_SUCCESS)
4919  {
4920  assert_release (false);
4921  return ER_FAILED;
4922  }
4923 
4924  fprintf (context->fp, "\n-----------------------------------------------\n");
4925  fprintf (context->fp, "\n Page %d \n", context->page_index);
4926 
4927  fprintf (context->fp, "\nPage_Id: {%d , %d}\n", PGBUF_PAGE_VPID_AS_ARGS (*page));
4928  fprintf (context->fp, "Directory Cnt: %d\n", CATALOG_GET_PGHEADER_DIR_COUNT (record.data));
4929  fprintf (context->fp, "Overflow Page Id: {%d , %d}\n\n", CATALOG_GET_PGHEADER_OVFL_PGID_PAGEID (record.data),
4931 
4932  spage_dump (thread_p, context->fp, *page, 0);
4933  context->page_index++;
4934  return NO_ERROR;
4935 }
4936 
4937 /*
4938  * catalog_file_map_overflow_count () - FILE_MAP_PAGE_FUNC to count overflows
4939  *
4940  * return : error code
4941  * thread_p (in) : thread entry
4942  * page (in) : catalog page pointer
4943  * stop (in) : not used
4944  * args (in) : overflow count
4945  */
4946 static int
4947 catalog_file_map_overflow_count (THREAD_ENTRY * thread_p, PAGE_PTR * page, bool * stop, void *args)
4948 {
4949  int *overflow_count = (int *) args;
4950  RECDES record;
4951 
4952  if (spage_get_record (thread_p, *page, CATALOG_HEADER_SLOT, &record, PEEK) != S_SUCCESS)
4953  {
4954  assert_release (false);
4955  return ER_FAILED;
4956  }
4958  {
4959  (*overflow_count)++;
4960  }
4961  return NO_ERROR;
4962 }
4963 
4964 /*
4965  * catalog_dump () - The content of catalog is dumped.
4966  * return: nothing
4967  * dump_flg(in): Catalog dump flag. Should be set to:
4968  * 0 : for catalog information content dump
4969  * 1 : for catalog and catalog index slotted page dump
4970  */
4971 void
4972 catalog_dump (THREAD_ENTRY * thread_p, FILE * fp, int dump_flag)
4973 {
4974  RECDES peek = RECDES_INITIALIZER; /* Record descriptor for peeking object */
4975  HFID root_hfid;
4976  OID class_oid;
4977 #if !defined(NDEBUG)
4978  char *classname = NULL;
4979 #endif
4980  HEAP_SCANCACHE scan_cache;
4982 
4983  REPR_ID *repr_id_set, *repr_id_p;
4984  DISK_REPR *disk_repr_p = NULL;
4985  int repr_count;
4986  CLS_INFO *class_info_p = NULL;
4987  int n, overflow_count;
4988 
4989  CATALOG_PAGE_DUMP_CONTEXT page_dump_context;
4990 
4991  fprintf (fp, "\n <<<<< C A T A L O G D U M P >>>>> \n\n");
4992 
4993  fprintf (fp, "\n Catalog Dump: \n\n");
4994 
4995  mvcc_snapshot = logtb_get_mvcc_snapshot (thread_p);
4996  if (mvcc_snapshot == NULL)
4997  {
4998  return;
4999  }
5000 
5001  /* Find every single class */
5002 
5003  if (boot_find_root_heap (&root_hfid) != NO_ERROR || HFID_IS_NULL (&root_hfid))
5004  {
5005  return;
5006  }
5007 
5008  if (heap_scancache_start (thread_p, &scan_cache, &root_hfid, oid_Root_class_oid, true, false, mvcc_snapshot) !=
5009  NO_ERROR)
5010  {
5011  return;
5012  }
5013 
5014  class_oid.volid = root_hfid.vfid.volid;
5015  class_oid.pageid = NULL_PAGEID;
5016  class_oid.slotid = NULL_SLOTID;
5017 
5018  while (heap_next (thread_p, &root_hfid, oid_Root_class_oid, &class_oid, &peek, &scan_cache, PEEK) == S_SUCCESS)
5019  {
5020 #if !defined(NDEBUG)
5021  classname = or_class_name (&peek);
5022  assert (classname != NULL);
5023  assert (strlen (classname) < 255);
5024 #endif
5025 
5026  fprintf (fp, " -------------------------------------------------\n");
5027  fprintf (fp, " CLASS_ID: { %d , %d , %d } \n", class_oid.volid, class_oid.pageid, class_oid.slotid);
5028 
5029  repr_id_set = NULL;
5030  catalog_get_representation_directory (thread_p, &class_oid, &repr_id_set, &repr_count);
5031  fprintf (fp, " Repr_cnt: %d \n", repr_count);
5032 
5033  /* get the representations identifiers set for the class */
5034  repr_id_p = repr_id_set;
5035  for (repr_id_p += repr_count - 1; repr_count; repr_id_p--, repr_count--)
5036  {
5037  if (*repr_id_p == NULL_REPRID)
5038  {
5039  continue;
5040  }
5041 
5042  fprintf (fp, " Repr_id: %d\n", *repr_id_p);
5043  }
5044 
5045  fprintf (fp, "\n");
5046 
5047  /* Get the class specific information for this class */
5048  class_info_p = catalog_get_class_info (thread_p, &class_oid, NULL);
5049  if (class_info_p != NULL)
5050  {
5051  fprintf (fp, " Class Specific Information: \n\n");
5052  fprintf (fp, " HFID: { vfid = { %d , %d }, hpgid = %d }\n", class_info_p->ci_hfid.vfid.fileid,
5053  class_info_p->ci_hfid.vfid.volid, class_info_p->ci_hfid.hpgid);
5054 
5055  fprintf (fp, " Total Pages in Heap: %d\n", class_info_p->ci_tot_pages);
5056  fprintf (fp, " Total Objects: %d\n", class_info_p->ci_tot_objects);
5057 
5058  fprintf (fp, " Representation directory OID: { %d , %d , %d } \n", class_info_p->ci_rep_dir.volid,
5059  class_info_p->ci_rep_dir.pageid, class_info_p->ci_rep_dir.slotid);
5060 
5061  catalog_free_class_info_and_init (class_info_p);
5062  }
5063 
5064  fprintf (fp, "\n");
5065 
5066  /* get the representations identifiers set for the class */
5067  repr_id_p = repr_id_set;
5068  for (repr_id_p += repr_count - 1; repr_count; repr_id_p--, repr_count--)
5069  {
5070  if (*repr_id_p == NULL_REPRID)
5071  {
5072  continue;
5073  }
5074 
5075  disk_repr_p = catalog_get_representation (thread_p, &class_oid, *repr_id_p, NULL);
5076  if (disk_repr_p == NULL)
5077  {
5078  continue; /* is error */
5079  }
5080 
5081  catalog_dump_representation (disk_repr_p);
5083  }
5084 
5085  if (repr_id_set != NULL)
5086  {
5087  free_and_init (repr_id_set);
5088  }
5089 
5090  heap_classrepr_dump_all (thread_p, fp, &class_oid);
5091  } /* while (...) */
5092 
5093  /* End the scan cursor */
5094  if (heap_scancache_end (thread_p, &scan_cache) != NO_ERROR)
5095  {
5096  return;
5097  }
5098 
5099  if (dump_flag == 1)
5100  {
5101  /* slotted page dump */
5102  fprintf (fp, "\n Catalog Directory Dump: \n\n");
5103 
5104  if (file_get_num_user_pages (thread_p, &catalog_Id.vfid, &n) != NO_ERROR)
5105  {
5106  ASSERT_ERROR ();
5107  return;
5108  }
5109  fprintf (fp, "Total Pages Count: %d\n\n", n);
5110 
5111  overflow_count = 0;
5112  if (file_map_pages (thread_p, &catalog_Id.vfid, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH,
5113  catalog_file_map_overflow_count, &overflow_count) != NO_ERROR)
5114  {
5115  ASSERT_ERROR ();
5116  return;
5117  }
5118 
5119  fprintf (fp, "Regular Pages Count: %d\n\n", n - overflow_count);
5120  fprintf (fp, "Overflow Pages Count: %d\n\n", overflow_count);
5121 
5122  page_dump_context.fp = fp;
5123  page_dump_context.page_index = 0;
5124  if (file_map_pages (thread_p, &catalog_Id.vfid, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH,
5125  catalog_file_map_page_dump, &page_dump_context) != NO_ERROR)
5126  {
5127  ASSERT_ERROR ();
5128  return;
5129  }
5130  }
5131 }
5132 
5133 static void
5135 {
5136  catalog_Hashmap.clear (thread_p);
5137 }
5138 
5139 
5140 /*
5141  * catalog_rv_new_page_redo () - Redo the initializations of a new catalog page
5142  * return: int
5143  * recv(in): Recovery structure
5144  */
5145 int
5147 {
5148  char data[CATALOG_PAGE_HEADER_SIZE + MAX_ALIGNMENT], *aligned_data;
5150  PGSLOTID slot_id;
5151  int success;
5152 
5153  aligned_data = PTR_ALIGN (data, MAX_ALIGNMENT);
5154 
5155  catalog_clear_hash_table (thread_p);
5156 
5157  (void) pgbuf_set_page_ptype (thread_p, recv_p->pgptr, PAGE_CATALOG);
5158 
5160 
5161  recdes_set_data_area (&record, aligned_data, CATALOG_PAGE_HEADER_SIZE);
5162  catalog_put_page_header (record.data, (CATALOG_PAGE_HEADER *) recv_p->data);
5163  success = spage_insert (thread_p, recv_p->pgptr, &record, &slot_id);
5164 
5165  if (success != SP_SUCCESS || slot_id != CATALOG_HEADER_SLOT)
5166  {
5167  if (success != SP_SUCCESS)
5168  {
5170  }
5171  assert (er_errid () != NO_ERROR);
5172  return er_errid ();
5173  }
5174 
5175  pgbuf_set_dirty (thread_p, recv_p->pgptr, DONT_FREE);
5176  return NO_ERROR;
5177 }
5178 
5179 /*
5180  * catalog_rv_insert_redo () - Redo the insertion of a record at a specific slot.
5181  * return: int
5182  * recv(in): Recovery structure
5183  */
5184 int
5186 {
5187  PGSLOTID slot_id;
5188  RECDES record;
5189  int success;
5190 
5191  catalog_clear_hash_table (thread_p);
5192 
5193  slot_id = recv_p->offset;
5194 
5195  recdes_set_data_area (&record, (char *) (recv_p->data) + sizeof (record.type), recv_p->length - sizeof (record.type));
5196  record.length = record.area_size;
5197  record.type = *(INT16 *) (recv_p->data);
5198 
5199  success = spage_insert_for_recovery (thread_p, recv_p->pgptr, slot_id, &record);
5200  if (success != SP_SUCCESS)
5201  {
5202  if (success != SP_ERROR)
5203  {
5205  }
5206  assert (er_errid () != NO_ERROR);
5207  return er_errid ();
5208  }
5209 
5210  pgbuf_set_dirty (thread_p, recv_p->pgptr, DONT_FREE);
5211  return NO_ERROR;
5212 }
5213 
5214 /*
5215  * catalog_rv_insert_undo () - Undo the insert of a record by deleting the record.
5216  * return: int
5217  * recv(in): Recovery structure
5218  */
5219 int
5221 {
5222  PGSLOTID slot_id;
5223 
5224  catalog_clear_hash_table (thread_p);
5225 
5226  slot_id = recv_p->offset;
5227  (void) spage_delete_for_recovery (thread_p, recv_p->pgptr, slot_id);
5228  pgbuf_set_dirty (thread_p, recv_p->pgptr, DONT_FREE);
5229 
5230  return NO_ERROR;
5231 }
5232 
5233 /*
5234  * catalog_rv_delete_redo () - Redo the deletion of a record.
5235  * return: int
5236  * recv(in): Recovery structure
5237  */
5238 int
5240 {
5241  PGSLOTID slot_id;
5242 
5243  catalog_clear_hash_table (thread_p);
5244 
5245  slot_id = recv_p->offset;
5246  (void) spage_delete (thread_p, recv_p->pgptr, slot_id);
5247  pgbuf_set_dirty (thread_p, recv_p->pgptr, DONT_FREE);
5248 
5249  return NO_ERROR;
5250 }
5251 
5252 
5253 /*
5254  * catalog_get_cardinality () - gets the cardinality of an index using
5255  * class OID, class DISK_REPR, index BTID
5256  * and partial key count
5257  * return: NO_ERROR, or error code
5258  * thread_p(in) : thread context
5259  * class_oid(in): class OID
5260  * disk_repr_p(in): class DISK_REPR
5261  * btid(in): index BTID
5262  * key_pos(in) : partial key (i-th column from index definition)
5263  * cardinality(out): number of distinct values
5264  *
5265  */
5266 int
5267 catalog_get_cardinality (THREAD_ENTRY * thread_p, OID * class_oid, DISK_REPR * rep, BTID * btid, const int key_pos,
5268  int *cardinality)
5269 {
5270  int idx_cnt;
5271  int att_cnt;
5272  int error = NO_ERROR;
5273  BTREE_STATS *p_stat_info = NULL;
5274  BTREE_STATS *curr_stat_info = NULL;
5275  DISK_ATTR *disk_attr_p = NULL;
5276  BTID curr_bitd;
5277  bool is_btree_found;
5278  DISK_REPR *disk_repr_p = NULL;
5279  bool free_disk_rep = false;
5280  int key_size;
5281  OID *partitions = NULL;
5282  int count = 0;
5283  CLS_INFO *subcls_info = NULL;
5284  DISK_REPR *subcls_disk_rep = NULL;
5285  OR_CLASSREP *subcls_rep = NULL;
5286  OR_CLASSREP *cls_rep = NULL;
5287  DISK_ATTR *subcls_attr = NULL;
5288  const BTREE_STATS *subcls_stats = NULL;
5289  REPR_ID subcls_repr_id;
5290  int subcls_idx_cache;
5291  int idx_cache;
5292  int i;
5293  bool is_subcls_attr_found = false;
5294  bool free_cls_rep = false;
5296  OID dir_oid;
5297 
5298  assert (class_oid != NULL && btid != NULL && cardinality != NULL);
5299  *cardinality = -1;
5300 
5301  if (rep != NULL)
5302  {
5303  disk_repr_p = rep;
5304  }
5305  else
5306  {
5307  int repr_id;
5308 
5309  error = catalog_get_dir_oid_from_cache (thread_p, class_oid, &dir_oid);
5310  if (error != NO_ERROR)
5311  {
5312  goto exit;
5313  }
5314 
5315  catalog_access_info.class_oid = class_oid;
5316  catalog_access_info.dir_oid = &dir_oid;
5317  error = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK);
5318  if (error != NO_ERROR)
5319  {
5320  goto exit;
5321  }
5322 
5323  /* get last representation id, if is not already known */
5324  error = catalog_get_last_representation_id (thread_p, class_oid, &repr_id);
5325  if (error != NO_ERROR)
5326  {
5327  goto exit;
5328  }
5329 
5330  /* get disk representation : the disk representation contains a some pre-filled BTREE statistics, but no partial
5331  * keys info yet */
5332  disk_repr_p = catalog_get_representation (thread_p, class_oid, repr_id, &catalog_access_info);
5333  if (disk_repr_p == NULL)
5334  {
5335  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_UNEXPECTED, 1, "Disk representation not found.");
5336  error = ER_UNEXPECTED;
5337  goto exit;
5338  }
5339  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
5340  free_disk_rep = true;
5341  }
5342 
5343  cls_rep = heap_classrepr_get (thread_p, class_oid, NULL, NULL_REPRID, &idx_cache);
5344  if (cls_rep == NULL)
5345  {
5346  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_UNEXPECTED, 1, "Class representation not found.");
5347  error = ER_UNEXPECTED;
5348  goto exit_cleanup;
5349  }
5350  free_cls_rep = true;
5351 
5352  /* There should be only one OR_ATTRIBUTE element that contains the index; this is the element corresponding to the
5353  * attribute which is the first key in the index */
5354  p_stat_info = NULL;
5355  is_btree_found = false;
5356  /* first, search in the fixed attributes : */
5357  for (att_cnt = 0, disk_attr_p = disk_repr_p->fixed; att_cnt < disk_repr_p->n_fixed; att_cnt++, disk_attr_p++)
5358  {
5359  /* search for BTID in each BTREE_STATS element from current attribute */
5360  for (idx_cnt = 0, curr_stat_info = disk_attr_p->bt_stats; idx_cnt < disk_attr_p->n_btstats;
5361  idx_cnt++, curr_stat_info++)
5362  {
5363  curr_bitd = curr_stat_info->btid;
5364  if (BTID_IS_EQUAL (&curr_bitd, btid))
5365  {
5366  p_stat_info = curr_stat_info;
5367  is_btree_found = true;
5368  break;
5369  }
5370  }
5371  if (is_btree_found)
5372  {
5373  break;
5374  }
5375  }
5376 
5377  if (!is_btree_found)
5378  {
5379  assert_release (p_stat_info == NULL);
5380  /* not found, repeat the search for variable attributes */
5381  for (att_cnt = 0, disk_attr_p = disk_repr_p->variable; att_cnt < disk_repr_p->n_variable;
5382  att_cnt++, disk_attr_p++)
5383  {
5384  /* search for BTID in each BTREE_STATS element from current attribute */
5385  for (idx_cnt = 0, curr_stat_info = disk_attr_p->bt_stats; idx_cnt < disk_attr_p->n_btstats;
5386  idx_cnt++, curr_stat_info++)
5387  {
5388  curr_bitd = curr_stat_info->btid;
5389  if (BTID_IS_EQUAL (&curr_bitd, btid))
5390  {
5391  p_stat_info = curr_stat_info;
5392  is_btree_found = true;
5393  break;
5394  }
5395  }
5396  if (is_btree_found)
5397  {
5398  break;
5399  }
5400  }
5401  }
5402 
5403  if (!is_btree_found)
5404  {
5405  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_UNEXPECTED, 1, "B-Tree not found.");
5406  error = ER_UNEXPECTED;
5407  goto exit_cleanup;
5408  }
5409 
5410  assert_release (p_stat_info != NULL);
5411  assert_release (BTID_IS_EQUAL (&(p_stat_info->btid), btid));
5412  assert_release (p_stat_info->pkeys_size > 0);
5414 
5415  /* since btree_get_stats is too slow, use the old statistics. the user must previously execute 'update statistics on
5416  * class_name', in order to get updated statistics. */
5417 
5418  if (TP_DOMAIN_TYPE (p_stat_info->key_type) == DB_TYPE_MIDXKEY)
5419  {
5420  key_size = tp_domain_size (p_stat_info->key_type->setdomain);
5421  }
5422  else
5423  {
5424  key_size = 1;
5425  }
5426 
5427  if (key_pos >= key_size || key_pos < 0)
5428  {
5430  goto exit_cleanup;
5431  }
5432 
5433  error = partition_get_partition_oids (thread_p, class_oid, &partitions, &count);
5434  if (error != NO_ERROR)
5435  {
5436  goto exit_cleanup;
5437  }
5438 
5439  if (count == 0)
5440  {
5441  *cardinality = p_stat_info->keys;
5442  }
5443  else
5444  {
5445  *cardinality = 0;
5446  for (i = 0; i < count; i++)
5447  {
5448  /* clean subclass loaded in previous iteration */
5449  if (subcls_info != NULL)
5450  {
5451  catalog_free_class_info_and_init (subcls_info);
5452  }
5453  if (subcls_disk_rep != NULL)
5454  {
5455  catalog_free_representation_and_init (subcls_disk_rep);
5456  }
5457  if (subcls_rep != NULL)
5458  {
5459  heap_classrepr_free_and_init (subcls_rep, &subcls_idx_cache);
5460  }
5461 
5462  if (catalog_get_dir_oid_from_cache (thread_p, &partitions[i], &dir_oid) != NO_ERROR)
5463  {
5464  continue;
5465  }
5466 
5467  catalog_access_info.class_oid = &partitions[i];
5468  catalog_access_info.dir_oid = &dir_oid;
5469  error = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK);
5470  if (error != NO_ERROR)
5471  {
5472  goto exit_cleanup;
5473  }
5474 
5475  /* load new subclass */
5476  subcls_info = catalog_get_class_info (thread_p, &partitions[i], &catalog_access_info);
5477  if (subcls_info == NULL)
5478  {
5479  assert (er_errid () != NO_ERROR);
5480  error = er_errid ();
5481  goto exit_cleanup;
5482  }
5483 
5484  /* get disk repr for subclass */
5485  error = catalog_get_last_representation_id (thread_p, &partitions[i], &subcls_repr_id);
5486  if (error != NO_ERROR)
5487  {
5488  goto exit_cleanup;
5489  }
5490 
5491  subcls_disk_rep = catalog_get_representation (thread_p, &partitions[i], subcls_repr_id, &catalog_access_info);
5492  if (subcls_disk_rep == NULL)
5493  {
5494  assert (er_errid () != NO_ERROR);
5495  error = er_errid ();
5496  goto exit_cleanup;
5497  }
5498  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
5499 
5500  subcls_rep = heap_classrepr_get (thread_p, &partitions[i], NULL, NULL_REPRID, &subcls_idx_cache);
5501  if (subcls_rep == NULL)
5502  {
5503  error = ER_FAILED;
5504  goto exit_cleanup;
5505  }
5506 
5507  is_subcls_attr_found = false;
5508  for (att_cnt = 0, subcls_attr = subcls_disk_rep->fixed; att_cnt < subcls_disk_rep->n_fixed;
5509  att_cnt++, subcls_attr++)
5510  {
5511  if (disk_attr_p->id == subcls_attr->id)
5512  {
5513  is_subcls_attr_found = true;
5514  break;
5515  }
5516  }
5517  if (!is_subcls_attr_found)
5518  {
5519  for (att_cnt = 0, subcls_attr = subcls_disk_rep->variable; att_cnt < subcls_disk_rep->n_variable;
5520  att_cnt++, subcls_attr++)
5521  {
5522  if (disk_attr_p->id == subcls_attr->id)
5523  {
5524  is_subcls_attr_found = true;
5525  break;
5526  }
5527  }
5528  }
5529 
5530  if (!is_subcls_attr_found)
5531  {
5532  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_UNEXPECTED, 1, "Attribute of subclass not found.");
5533  error = ER_UNEXPECTED;
5534  goto exit_cleanup;
5535  }
5536  subcls_stats = stats_find_inherited_index_stats (cls_rep, subcls_rep, subcls_attr, btid);
5537  if (subcls_stats == NULL)
5538  {
5539  error = ER_FAILED;
5540  goto exit_cleanup;
5541  }
5542 
5543  *cardinality = *cardinality + subcls_stats->keys;
5544  }
5545  }
5546 
5547 exit_cleanup:
5548  if (free_disk_rep)
5549  {
5551  }
5552  if (free_cls_rep)
5553  {
5554  heap_classrepr_free_and_init (cls_rep, &idx_cache);
5555  }
5556  if (subcls_info != NULL)
5557  {
5558  catalog_free_class_info_and_init (subcls_info);
5559  }
5560  if (subcls_disk_rep != NULL)
5561  {
5562  catalog_free_representation_and_init (subcls_disk_rep);
5563  }
5564  if (subcls_rep != NULL)
5565  {
5566  heap_classrepr_free_and_init (subcls_rep, &subcls_idx_cache);
5567  }
5568  if (partitions != NULL)
5569  {
5570  db_private_free (thread_p, partitions);
5571  }
5572 exit:
5573  catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, error);
5574  return error;
5575 }
5576 
5577 /*
5578  * catalog_get_cardinality_by_name () - gets the cardinality of an index using
5579  * its name and partial key count
5580  * return: NO_ERROR, or error code
5581  * thread_p(in) : thread context
5582  * class_name(in): name of class
5583  * index_name(in): name of index
5584  * key_pos(in) : partial key (i-th column from index definition)
5585  * cardinality(out): number of distinct values
5586  *
5587  */
5588 int
5589 catalog_get_cardinality_by_name (THREAD_ENTRY * thread_p, const char *class_name, const char *index_name,
5590  const int key_pos, int *cardinality)
5591 {
5592  int error = NO_ERROR;
5593  BTID found_btid;
5594  BTID curr_bitd;
5595  OID class_oid;
5596  char cls_lower[DB_MAX_IDENTIFIER_LENGTH] = { 0 };
5597  LC_FIND_CLASSNAME status;
5598 
5599  BTID_SET_NULL (&found_btid);
5600  BTID_SET_NULL (&curr_bitd);
5601 
5602  assert (class_name != NULL);
5603  assert (index_name != NULL);
5604  assert (cardinality != NULL);
5605 
5606  *cardinality = -1;
5607 
5608  /* get class OID from class name */
5609  intl_identifier_lower (class_name, cls_lower);
5610 
5611  status = xlocator_find_class_oid (thread_p, cls_lower, &class_oid, NULL_LOCK);
5612  if (status == LC_CLASSNAME_ERROR)
5613  {
5615  return ER_FAILED;
5616  }
5617 
5618  if (status == LC_CLASSNAME_DELETED || OID_ISNULL (&class_oid))
5619  {
5621  goto exit;
5622  }
5623 
5624  if (lock_object (thread_p, &class_oid, oid_Root_class_oid, SCH_S_LOCK, LK_UNCOND_LOCK) != LK_GRANTED)
5625  {
5626  error = ER_FAILED;
5627  goto exit;
5628  }
5629 
5630  error = heap_get_btid_from_index_name (thread_p, &class_oid, index_name, &found_btid);
5631  if (error != NO_ERROR)
5632  {
5633  goto exit;
5634  }
5635 
5636  if (BTID_IS_NULL (&found_btid))
5637  {
5639  goto exit;
5640  }
5641 
5642  return catalog_get_cardinality (thread_p, &class_oid, NULL, &found_btid, key_pos, cardinality);
5643 
5644 exit:
5645  return error;
5646 }
5647 
5648 /*
5649  * catalog_rv_delete_undo () - Undo the deletion of a record.
5650  * return: int
5651  * recv(in): Recovery structure
5652  */
5653 int
5655 {
5656  catalog_clear_hash_table (thread_p);
5657  return catalog_rv_insert_redo (thread_p, recv_p);
5658 }
5659 
5660 /*
5661  * catalog_rv_update () - Recover an update either for undo or redo
5662  * return: int
5663  * recv(in): Recovery structure
5664  *
5665  * Note: Recover an update to a record in a slotted page
5666  */
5667 int
5669 {
5670  PGSLOTID slot_id;
5671  RECDES record;
5672 
5673  catalog_clear_hash_table (thread_p);
5674 
5675  slot_id = recv_p->offset;
5676 
5677  recdes_set_data_area (&record, (char *) (recv_p->data) + sizeof (record.type), recv_p->length - sizeof (record.type));
5678  record.length = record.area_size;
5679  record.type = *(INT16 *) (recv_p->data);
5680 
5681  if (spage_update (thread_p, recv_p->pgptr, slot_id, &record) != SP_SUCCESS)
5682  {
5683  assert (er_errid () != NO_ERROR);
5684  return er_errid ();
5685  }
5686 
5687  pgbuf_set_dirty (thread_p, recv_p->pgptr, DONT_FREE);
5688  return NO_ERROR;
5689 }
5690 
5691 /*
5692  * catalog_rv_ovf_page_logical_insert_undo () - Undo new overflow page creation.
5693  * return: int
5694  * recv(in): Recovery structure
5695  */
5696 int
5698 {
5699  VPID *vpid_p;
5700 
5701  catalog_clear_hash_table (thread_p);
5702 
5703  vpid_p = (VPID *) recv_p->data;
5704  return file_dealloc (thread_p, &catalog_Id.vfid, vpid_p, FILE_CATALOG);
5705 }
5706 
5707 /*
5708  * catalog_get_dir_oid_from_cache () - Get directory OID from cache or class record
5709  * return: error status
5710  * class_id_p(in): Class identifier
5711  * dir_oid_p(out): directory OID
5712  *
5713  */
5714 int
5715 catalog_get_dir_oid_from_cache (THREAD_ENTRY * thread_p, const OID * class_id_p, OID * dir_oid_p)
5716 {
5717  CATALOG_ENTRY *catalog_value_p;
5719  HEAP_SCANCACHE scan_cache;
5720  RECDES record = { -1, -1, REC_HOME, NULL };
5721  int error = NO_ERROR;
5722 
5723  assert (dir_oid_p != NULL);
5724  OID_SET_NULL (dir_oid_p);
5725 
5726  catalog_key.page_id = class_id_p->pageid;
5727  catalog_key.volid = class_id_p->volid;
5728  catalog_key.slot_id = class_id_p->slotid;
5729  catalog_key.repr_id = CATALOG_DIR_REPR_KEY;
5730 
5731  catalog_value_p = catalog_Hashmap.find (thread_p, catalog_key);
5732  if (catalog_value_p != NULL)
5733  {
5734  /* entry already exists */
5735  dir_oid_p->volid = catalog_value_p->key.r_page_id.volid;
5736  dir_oid_p->pageid = catalog_value_p->key.r_page_id.pageid;
5737  dir_oid_p->slotid = catalog_value_p->key.r_slot_id;
5738 
5739  /* end transaction */
5740  catalog_Hashmap.unlock (thread_p, catalog_value_p);
5741  return NO_ERROR;
5742  }
5743 
5744  /* not found in cache, get it from class record */
5745  heap_scancache_quick_start_root_hfid (thread_p, &scan_cache);
5746 
5747  if (heap_get_class_record (thread_p, class_id_p, &record, &scan_cache, PEEK) == S_SUCCESS)
5748  {
5749  or_class_rep_dir (&record, dir_oid_p);
5750  }
5751  else
5752  {
5753  error = er_errid ();
5754  if (error == NO_ERROR)
5755  {
5756  error = ER_FAILED;
5757  }
5758 
5759  heap_scancache_end (thread_p, &scan_cache);
5760 
5761  return error;
5762  }
5763 
5764  heap_scancache_end (thread_p, &scan_cache);
5765 
5766  if (OID_ISNULL (dir_oid_p))
5767  {
5768  /* directory not created yet, don't cache NULL OID */
5769  return NO_ERROR;
5770  }
5771 
5772  catalog_key.r_page_id.pageid = dir_oid_p->pageid;
5773  catalog_key.r_page_id.volid = dir_oid_p->volid;
5774  catalog_key.r_slot_id = dir_oid_p->slotid;
5775 
5776  /* insert value */
5777  (void) catalog_Hashmap.find_or_insert (thread_p, catalog_key, catalog_value_p);
5778  if (catalog_value_p != NULL)
5779  {
5780  catalog_Hashmap.unlock (thread_p, catalog_value_p);
5781  return NO_ERROR;
5782  }
5783  else
5784  {
5785  assert (false);
5786  return ER_FAILED;
5787  }
5788 
5789  return NO_ERROR;
5790 }
5791 
5792 /*
5793  * catalog_start_access_with_dir_oid () - starts an access on catalog using directory OID for locking purpose
5794  * return: error code
5795  * catalog_access_info(in/out): catalog access helper structure
5796  * lock_mode(in): should be X_LOCK for update on catalog and S_LOCK for read
5797  */
5798 int
5800 {
5801 #if defined (SERVER_MODE)
5802  LOCK current_lock;
5803 #endif /* SERVER_MODE */
5804  int error_code = NO_ERROR;
5805  int lk_grant_code;
5806  OID virtual_class_dir_oid;
5807 
5808  assert (catalog_access_info != NULL);
5809 
5810  assert (catalog_access_info->access_started == false);
5811  if (catalog_access_info->access_started == true)
5812  {
5813  (void) catalog_end_access_with_dir_oid (thread_p, catalog_access_info, NO_ERROR);
5814  }
5815 
5816  if (BO_IS_SERVER_RESTARTED () == false || OID_ISNULL (catalog_access_info->dir_oid))
5817  {
5818  /* server not started or class dir not created yet: do not use locking */
5819  return NO_ERROR;
5820  }
5821 
5822  catalog_access_info->need_unlock = false;
5823  catalog_access_info->is_update = (lock_mode == X_LOCK) ? true : false;
5824 
5825  if (lock_mode == X_LOCK)
5826  {
5827  log_sysop_start (thread_p);
5828 #if !defined (NDEBUG)
5829  catalog_access_info->is_systemop_started = true;
5830 #endif
5831  }
5832 
5833  OID_GET_VIRTUAL_CLASS_OF_DIR_OID (catalog_access_info->class_oid, &virtual_class_dir_oid);
5834 #if defined (SERVER_MODE)
5835  current_lock = lock_get_object_lock (catalog_access_info->dir_oid, &virtual_class_dir_oid);
5836  if (current_lock != NULL_LOCK)
5837  {
5838  assert (false);
5839 
5840  if (lock_mode == X_LOCK)
5841  {
5842  log_sysop_abort (thread_p);
5843  }
5844 
5845  error_code = ER_FAILED;
5846  return error_code;
5847  }
5848 #endif /* SERVER_MODE */
5849 
5850  /* before go further, we should get the lock to disable updating schema */
5851  lk_grant_code = lock_object (thread_p, catalog_access_info->dir_oid, &virtual_class_dir_oid, lock_mode,
5852  LK_UNCOND_LOCK);
5853  if (lk_grant_code != LK_GRANTED)
5854  {
5855  /* deadlocked, timedout or interrupted */
5856  assert (lk_grant_code == LK_NOTGRANTED_DUE_ABORTED || lk_grant_code == LK_NOTGRANTED_DUE_TIMEOUT
5857  || lk_grant_code == LK_NOTGRANTED_DUE_ERROR);
5858 
5859  if (catalog_access_info->class_name == NULL)
5860  {
5861  if (heap_get_class_name (thread_p, catalog_access_info->class_oid, &catalog_access_info->class_name) !=
5862  NO_ERROR)
5863  {
5864  /* ignore */
5865  er_clear ();
5866  }
5867  else if (catalog_access_info->class_name != NULL)
5868  {
5869  catalog_access_info->need_free_class_name = true;
5870  }
5871  }
5872 
5873  if (lock_mode == X_LOCK)
5874  {
5875  log_sysop_abort (thread_p);
5876  }
5877 
5878 #if !defined (NDEBUG)
5879  catalog_access_info->is_systemop_started = false;
5880 #endif
5881 
5882  error_code = ER_UPDATE_STAT_CANNOT_GET_LOCK;
5883  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1,
5884  catalog_access_info->class_name ? catalog_access_info->class_name : "*UNKNOWN-CLASS*");
5885 
5886  goto error;
5887  }
5888 
5889  catalog_access_info->need_unlock = true;
5890  catalog_access_info->access_started = true;
5891 
5892  return error_code;
5893 
5894 error:
5895  return error_code;
5896 }
5897 
5898 /*
5899  * catalog_end_access_with_dir_oid () - ends access on catalog using directory OID
5900  * return: error code
5901  * catalog_access_info(in/out): catalog access helper structure
5902  * error(in): error code
5903  */
5904 int
5906 {
5907  OID virtual_class_dir_oid;
5908  LOCK current_lock;
5909 
5910  assert (catalog_access_info != NULL);
5911 
5912  if (catalog_access_info->access_started == false)
5913  {
5914  assert (catalog_access_info->need_unlock == false);
5915 #if !defined (NDEBUG)
5916  assert (catalog_access_info->is_systemop_started == false);
5917 #endif
5918  return NO_ERROR;
5919  }
5920 
5921  assert (BO_IS_SERVER_RESTARTED () == true);
5922 
5923  if (catalog_access_info->is_update == true)
5924  {
5925  if (error != NO_ERROR)
5926  {
5927  log_sysop_abort (thread_p);
5928  }
5929  else
5930  {
5931 #if defined (SERVER_MODE)
5932  current_lock = lock_get_object_lock (catalog_access_info->class_oid, oid_Root_class_oid);
5933 
5934  if (current_lock == SCH_M_LOCK)
5935  {
5936  /* when class was created or schema was changed commit the statistics changes along with schema change */
5937  log_sysop_attach_to_outer (thread_p);
5938  }
5939  else
5940  {
5941  /* this case applies with UPDATE STATISTICS */
5942  log_sysop_commit (thread_p);
5943  }
5944 #else
5945  log_sysop_attach_to_outer (thread_p);
5946 #endif /* SERVER_MODE */
5947  }
5948 #if !defined (NDEBUG)
5949  catalog_access_info->is_systemop_started = false;
5950 #endif
5951  }
5952 #if !defined (NDEBUG)
5953  assert (catalog_access_info->is_systemop_started == false);
5954 #endif
5955 
5956  OID_GET_VIRTUAL_CLASS_OF_DIR_OID (catalog_access_info->class_oid, &virtual_class_dir_oid);
5957  if (catalog_access_info->need_unlock == true)
5958  {
5959  current_lock = catalog_access_info->is_update ? X_LOCK : S_LOCK;
5960  lock_unlock_object_donot_move_to_non2pl (thread_p, catalog_access_info->dir_oid, &virtual_class_dir_oid,
5961  current_lock);
5962  }
5963 
5964  catalog_access_info->access_started = false;
5965  catalog_access_info->is_update = false;
5966  catalog_access_info->need_unlock = false;
5967 
5968  if (catalog_access_info->class_name != NULL && catalog_access_info->need_free_class_name == true)
5969  {
5970  free_and_init (catalog_access_info->class_name);
5971  }
5972  catalog_access_info->need_free_class_name = false;
5973 
5974  return NO_ERROR;
5975 }
PGLENGTH offset
Definition: recovery.h:201
char * PAGE_PTR
#define ER_PAGE_LATCH_ABORTED
Definition: error_code.h:1074
#define PGBUF_PAGE_VPID_AS_ARGS(pg)
Definition: page_buffer.h:53
#define OR_GET_HFID(ptr, hfid)
#define OR_PUT_OID(ptr, oid)
int ci_tot_pages
OID * oid_Root_class_oid
Definition: oid.c:73
#define CATALOG_DISK_ATTR_N_BTSTATS_OFF
#define CATALOG_DISK_REPR_RESERVED_1_OFF
#define CATALOG_CLS_INFO_REP_DIR_OFF
#define NO_ERROR
Definition: error_code.h:46
CLS_INFO * catalog_get_class_info(THREAD_ENTRY *thread_p, OID *class_id_p, CATALOG_ACCESS_INFO *catalog_access_info_p)
int area_size
#define ER_CT_MISSING_REPR_INFO
Definition: error_code.h:499
int or_rep_id(RECDES *record)
static int catalog_fetch_attribute_value(THREAD_ENTRY *thread_p, void *value, int length, CATALOG_RECORD *ct_recordp)
MVCC_SNAPSHOT * logtb_get_mvcc_snapshot(THREAD_ENTRY *thread_p)
#define LF_EM_NOT_USING_MUTEX
Definition: lock_free.h:59
void log_append_undoredo_data2(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, const VFID *vfid, PAGE_PTR pgptr, PGLENGTH offset, int undo_length, int redo_length, const void *undo_data, const void *redo_data)
Definition: log_manager.c:1861
#define BTREE_STATS_RESERVED_NUM
Definition: statistics.h:42
UINT64 del_id
static int catalog_sum_disk_attribute_size(DISK_ATTR *attrs_p, int count)
int catalog_reclaim_space(THREAD_ENTRY *thread_p)
#define BO_IS_SERVER_RESTARTED()
Definition: boot_sr.h:84
int catalog_delete(THREAD_ENTRY *thread_p, OID *class_oid_p)
#define ASSERT_ERROR()
INT32 pageid
static void catalog_update_max_space(VPID *page_id, PGLENGTH space)
static int catalog_put_record_into_page(THREAD_ENTRY *thread_p, CATALOG_RECORD *ct_recordp, int next, PGSLOTID *remembered_slotid)
int file_dealloc(THREAD_ENTRY *thread_p, const VFID *vfid, const VPID *vpid, FILE_TYPE file_type_hint)
#define CATALOG_DISK_REPR_N_FIXED_OFF
int spage_insert(THREAD_ENTRY *thread_p, PAGE_PTR page_p, RECDES *record_descriptor_p, PGSLOTID *out_slot_id_p)
#define CATALOG_CLS_INFO_RESERVED
#define CATALOG_BT_STATS_RESERVED_OFF
void unlock(cubthread::entry *thread_p, T *&t)
void recdes_set_data_area(RECDES *rec, char *data, int size)
#define CATALOG_BT_STATS_FUNC_INDEX_OFF
#define VPID_COPY(dest_ptr, src_ptr)
Definition: dbtype_def.h:909
#define CATALOG_GET_REPR_ITEM_COUNT(ptr)
CLS_INFO * catalog_update_class_info(THREAD_ENTRY *thread_p, OID *class_id_p, CLS_INFO *class_info_p, CATALOG_ACCESS_INFO *catalog_access_info_p, bool skip_logging)
#define ER_HEAP_NODATA_NEWADDRESS
Definition: error_code.h:107
static int catalog_assign_attribute(THREAD_ENTRY *thread_p, DISK_ATTR *disk_attr_p, CATALOG_RECORD *catalog_record_p)
DB_TYPE
Definition: dbtype_def.h:670
#define pthread_mutex_unlock(a)
static int catalog_drop_disk_representation_from_page(THREAD_ENTRY *thread_p, VPID *page_id, PGSLOTID slot_id)
#define ER_FAILED
Definition: error_code.h:47
BTREE_ROOT_HEADER * btree_get_root_header(THREAD_ENTRY *thread_p, PAGE_PTR page_ptr)
Definition: btree_load.c:309
void spage_initialize(THREAD_ENTRY *thread_p, PAGE_PTR page_p, INT16 slot_type, unsigned short alignment, bool is_saving)
int partition_get_partition_oids(THREAD_ENTRY *thread_p, const OID *class_oid, OID **partition_oids, int *count)
Definition: partition.c:3380
static void * catalog_entry_alloc(void)
DISK_ISVALID file_check_vpid(THREAD_ENTRY *thread_p, const VFID *vfid, const VPID *vpid_lookup)
int catalog_add_class_info(THREAD_ENTRY *thread_p, OID *class_id_p, CLS_INFO *class_info_p, CATALOG_ACCESS_INFO *catalog_access_info_p)
struct tp_domain * setdomain
Definition: object_domain.h:82
#define CATALOG_GET_PGHEADER_DIR_COUNT(ptr)
PGSLOTID slot_id
static void catalog_free_key_list(CATALOG_CLASS_ID_LIST *clsid_list)
#define SAFEGUARD_RVSPACE
Definition: slotted_page.h:53
#define ER_CT_UNKNOWN_REPRID
Definition: error_code.h:493
void orc_free_diskrep(DISK_REPR *rep)
static int catalog_drop_all_representation_and_class(THREAD_ENTRY *thread_p, OID *class_id)
static PAGE_PTR catalog_find_optimal_page(THREAD_ENTRY *thread_p, int size, VPID *page_id)
#define ASSERT_ERROR_AND_SET(error_code)
#define ER_UPDATE_STAT_CANNOT_GET_LOCK
Definition: error_code.h:1497
static void catalog_put_btree_statistics(char *rec_p, BTREE_STATS *stat_p)
Definition: lock_free.h:63
#define CATALOG_REPR_ITEM_SLOTID_OFF
char packed_key_domain[1]
Definition: btree_load.h:219
#define assert_release(e)
Definition: error_manager.h:96
#define CATALOG_PUT_PGHEADER_DIR_COUNT(ptr, val)
PGSLOTID r_slot_id
void pgbuf_set_dirty(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, bool free_page)
Definition: page_buffer.c:4280
unsigned int ci_time_stamp
int catalog_rv_insert_redo(THREAD_ENTRY *thread_p, LOG_RCV *recv_p)
void log_append_undo_data2(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, const VFID *vfid, PAGE_PTR pgptr, PGLENGTH offset, int length, const void *data)
Definition: log_manager.c:1933
static int catalog_drop(THREAD_ENTRY *thread_p, OID *class_id, REPR_ID repr_id)
int pkeys_size
Definition: statistics.h:66
INT16 VOLID
int lock_object(THREAD_ENTRY *thread_p, const OID *oid, const OID *class_oid, LOCK lock, int cond_flag)
void log_sysop_start(THREAD_ENTRY *thread_p)
Definition: log_manager.c:3578
static int catalog_store_disk_attribute(THREAD_ENTRY *thread_p, DISK_ATTR *disk_attrp, CATALOG_RECORD *ct_recordp, PGSLOTID *remembered_slotid)
int heap_scancache_quick_start_root_hfid(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache)
Definition: heap_file.c:19255
void catalog_initialize(CTID *catalog_id_p)
int xcatalog_check_rep_dir(THREAD_ENTRY *thread_p, OID *class_id_p, OID *rep_dir_p)
TP_DOMAIN * key_type
Definition: statistics.h:65
static int catalog_fetch_disk_representation(THREAD_ENTRY *thread_p, DISK_REPR *disk_reprp, CATALOG_RECORD *ct_recordp)
#define OID_SET_NULL(oidp)
Definition: oid.h:85
#define NULL_SLOTID
char * data
CATALOG_ENTRY * next
#define OR_GET_BYTE(ptr)
int32_t pageid
Definition: dbtype_def.h:879
INT32 root_pageid
INT32 hpgid
#define CATALOG_DISK_REPR_ID_OFF
#define BTID_IS_EQUAL(b1, b2)
int catalog_rv_ovf_page_logical_insert_undo(THREAD_ENTRY *thread_p, LOG_RCV *recv_p)
int er_errid(void)
static void catalog_delete_key(THREAD_ENTRY *thread_p, OID *class_id_p, REPR_ID repr_id)
#define SP_SUCCESS
Definition: slotted_page.h:50
#define PTR_ALIGN(addr, boundary)
Definition: memory_alloc.h:77
void lock_unlock_object_donot_move_to_non2pl(THREAD_ENTRY *thread_p, const OID *oid, const OID *class_oid, LOCK lock)
int catalog_update(THREAD_ENTRY *thread_p, RECDES *record_p, OID *class_oid_p)
#define CATALOG_BT_STATS_PKEYS_OFF
bool erase(cubthread::entry *thread_p, Key &key)
#define OID_AS_ARGS(oidp)
Definition: oid.h:39
#define CATALOG_GET_PGHEADER_OVFL_PGID_PAGEID(ptr)
void or_class_hfid(RECDES *record, HFID *hfid)
TP_DOMAIN tp_Null_domain
#define er_log_debug(...)
PGSLOTID spage_delete_for_recovery(THREAD_ENTRY *thread_p, PAGE_PTR page_p, PGSLOTID slot_id)
#define CATALOG_PUT_PGHEADER_OVFL_PGID_VOLID(ptr, val)
static int catalog_put_representation_item(THREAD_ENTRY *thread_p, OID *class_id, CATALOG_REPR_ITEM *repr_item, OID *rep_dir_p)
int heap_scancache_end(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache)
Definition: heap_file.c:7195
static void catalog_copy_btree_statistic(BTREE_STATS *new_btree_stats_p, int new_btree_stats_count, BTREE_STATS *pre_btree_stats_p, int pre_btree_stats_count)
static CATALOG_MAX_SPACE catalog_Max_space
#define MAX_ALIGNMENT
Definition: memory_alloc.h:70
#define CATALOG_ACCESS_INFO_INITIALIZER
#define ER_CT_INVALID_REPRID
Definition: error_code.h:494
#define COPY_OID(dest_oid_ptr, src_oid_ptr)
Definition: oid.h:63
static void catalog_put_page_header(char *rec_p, CATALOG_PAGE_HEADER *header_p)
LOCK lock_get_object_lock(const OID *oid, const OID *class_oid)
SCAN_CODE spage_get_record(THREAD_ENTRY *thread_p, PAGE_PTR page_p, PGSLOTID slot_id, RECDES *record_descriptor_p, int is_peeking)
#define OID_GET_VIRTUAL_CLASS_OF_DIR_OID(class_oidp, virtual_oidp)
Definition: oid.h:140
static void catalog_put_repr_item_to_record(char *rec_p, CATALOG_REPR_ITEM *item_p)
bool find_or_insert(cubthread::entry *thread_p, Key &key, T *&t)
int catalog_start_access_with_dir_oid(THREAD_ENTRY *thread_p, CATALOG_ACCESS_INFO *catalog_access_info, LOCK lock_mode)
#define CATALOG_DISK_ATTR_POSITION_OFF
int ci_tot_objects
int file_create_with_npages(THREAD_ENTRY *thread_p, FILE_TYPE file_type, int npages, FILE_DESCRIPTORS *des, VFID *vfid)
void THREAD_ENTRY
#define NULL_PAGEID
int catalog_insert(THREAD_ENTRY *thread_p, RECDES *record_p, OID *class_oid_p, OID *rep_dir_p)
#define pgbuf_unfix_and_init(thread_p, pgptr)
Definition: page_buffer.h:63
#define CATALOG_REPR_ITEM_REPRID_OFF
VFID vfid
#define CATALOG_CLS_INFO_TOT_OBJS_OFF
static int catalog_drop_all(THREAD_ENTRY *thread_p, OID *class_id)
static void catalog_put_class_info_to_record(char *rec_p, CLS_INFO *class_info_p)
int intl_identifier_lower(const char *src, char *dst)
int spage_update(THREAD_ENTRY *thread_p, PAGE_PTR page_p, PGSLOTID slot_id, const RECDES *record_descriptor_p)
LOCK
#define FREE(PTR)
Definition: cas_common.h:56
void or_class_rep_dir(RECDES *record, OID *rep_dir_p)
int heap_scancache_start(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache, const HFID *hfid, const OID *class_oid, int cache_last_fix_page, int is_indexscan, MVCC_SNAPSHOT *mvcc_snapshot)
Definition: heap_file.c:6833
#define ER_UNEXPECTED
Definition: error_code.h:1254
int boot_find_root_heap(HFID *root_hfid_p)
Definition: boot_sr.c:325
int file_alloc_sticky_first_page(THREAD_ENTRY *thread_p, const VFID *vfid, FILE_INIT_PAGE_FUNC f_init, void *f_init_args, VPID *vpid_out, PAGE_PTR *page_out)
int spage_max_record_size(void)
Definition: slotted_page.c:848
void spage_dump(THREAD_ENTRY *thread_p, FILE *fp, PAGE_PTR page_p, int is_record_printed)
EHID * xehash_create(THREAD_ENTRY *thread_p, EHID *ehid, DB_TYPE key_type, int exp_num_entries, OID *class_oid, int attr_id, bool is_tmp)
#define RECDES_INITIALIZER
void catalog_dump(THREAD_ENTRY *thread_p, FILE *fp, int dump_flag)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
int catalog_end_access_with_dir_oid(THREAD_ENTRY *thread_p, CATALOG_ACCESS_INFO *catalog_access_info, int error)
int spage_max_space_for_new_record(THREAD_ENTRY *thread_p, PAGE_PTR page_p)
Definition: slotted_page.c:984
CATALOG_CLASS_ID_LIST * next
static int catalog_file_map_page_dump(THREAD_ENTRY *thread_p, PAGE_PTR *page, bool *stop, void *args)
static int catalog_file_map_overflow_count(THREAD_ENTRY *thread_p, PAGE_PTR *page, bool *stop, void *args)
static void catalog_get_disk_attribute(DISK_ATTR *attr_p, char *rec_p)
#define CATALOG_DISK_REPR_FIXED_LENGTH_OFF
PAGE_PTR pgptr
Definition: recovery.h:199
#define assert(x)
void log_skip_logging(THREAD_ENTRY *thread_p, LOG_DATA_ADDR *addr)
Definition: log_manager.c:3244
static void catalog_dump_disk_attribute(DISK_ATTR *atr)
#define CATALOG_HEADER_SLOT
int * pkeys
Definition: statistics.h:67
BTREE_STATS * bt_stats
#define ER_LC_UNKNOWN_CLASSNAME
Definition: error_code.h:121
static int catalog_get_representation_item(THREAD_ENTRY *thread_p, OID *class_id, CATALOG_REPR_ITEM *repr_item)
int32_t fileid
Definition: dbtype_def.h:886
REPR_ID repr_id
bool pgbuf_check_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, PAGE_TYPE ptype)
int file_get_num_user_pages(THREAD_ENTRY *thread_p, const VFID *vfid, int *n_user_pages_out)
T * find(cubthread::entry *thread_p, Key &key)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
#define CATALOG_CLS_INFO_HFID_OFF
static void catalog_put_disk_representation(char *rec_p, DISK_REPR *disk_repr_p)
PGBUF_LATCH_MODE
Definition: page_buffer.h:176
int catalog_rv_update(THREAD_ENTRY *thread_p, LOG_RCV *recv_p)
void heap_classrepr_dump_all(THREAD_ENTRY *thread_p, FILE *fp, OID *class_oid)
Definition: heap_file.c:16874
#define CATALOG_REPR_ITEM_PAGEID_VOLID_OFF
LC_FIND_CLASSNAME xlocator_find_class_oid(THREAD_ENTRY *thread_p, const char *classname, OID *class_oid, LOCK lock)
Definition: locator_sr.c:1033
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define CATALOG_BT_STATS_KEYS_OFF
static void catalog_get_btree_statistics(BTREE_STATS *stat_p, char *rec_p)
#define OID_ISTEMP(oidp)
Definition: oid.h:80
#define CATALOG_PAGE_HEADER_SIZE
int tp_domain_size(const TP_DOMAIN *domain)
#define CATALOG_GET_REPR_ITEM_SLOTID(ptr)
#define OR_GET_OID(ptr, oid)
void log_append_redo_recdes2(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, const VFID *vfid, PAGE_PTR pgptr, PGLENGTH offset, const RECDES *recdes)
Definition: log_manager.c:2579
#define BTREE_STATS_PKEYS_NUM
Definition: statistics.h:41
#define DB_MAX_IDENTIFIER_LENGTH
Definition: dbtype_def.h:495
CATALOG_KEY key
#define CATALOG_DISK_REPR_SIZE
void lock_unlock_object(THREAD_ENTRY *thread_p, const OID *oid, const OID *class_oid, LOCK lock, bool force)
#define CATALOG_DISK_ATTR_VAL_LENGTH_OFF
static void catalog_get_class_info_from_record(CLS_INFO *class_info_p, char *rec_p)
int catalog_rv_delete_redo(THREAD_ENTRY *thread_p, LOG_RCV *recv_p)
#define VPID_EQ(vpid_ptr1, vpid_ptr2)
Definition: dbtype_def.h:915
#define CATALOG_HASH_SIZE
#define CATALOG_REPR_ITEM_PAGEID_PAGEID_OFF
#define CATALOG_DISK_REPR_N_VARIABLE_OFF
short volid
Definition: dbtype_def.h:880
int catalog_rv_delete_undo(THREAD_ENTRY *thread_p, LOG_RCV *recv_p)
void catalog_free_representation(DISK_REPR *repr_p)
void orc_free_class_info(CLS_INFO *info)
#define OID_EQ(oidp1, oidp2)
Definition: oid.h:92
#define CATALOG_BT_STATS_HEIGHT_OFF
static int catalog_drop_representation_class_from_page(THREAD_ENTRY *thread_p, VPID *dir_pgid, PAGE_PTR *dir_pgptr, VPID *page_id, PGSLOTID slot_id)
#define CATALOG_BT_STATS_PAGES_OFF
#define heap_classrepr_free_and_init(class_repr, idxp)
Definition: heap_file.h:91
DISK_REPR * orc_diskrep_from_record(THREAD_ENTRY *thread_p, RECDES *record)
int catalog_add_representation(THREAD_ENTRY *thread_p, OID *class_id_p, REPR_ID repr_id, DISK_REPR *disk_repr_p, OID *rep_dir_p, CATALOG_ACCESS_INFO *catalog_access_info_p)
VFID vfid
#define TP_DOMAIN_TYPE(dom)
int length
Definition: recovery.h:202
#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)
int catalog_get_representation_directory(THREAD_ENTRY *thread_p, OID *class_id_p, REPR_ID **repr_id_set_p, int *repr_count_p)
static int catalog_entry_free(void *ent)
PGNSLOTS spage_number_of_records(PAGE_PTR page_p)
Definition: slotted_page.c:860
struct disk_attribute * variable
#define CATALOG_DISK_ATTR_CLASSOID_OFF
static void catalog_get_disk_representation(DISK_REPR *disk_repr_p, char *rec_p)
int catalog_rv_insert_undo(THREAD_ENTRY *thread_p, LOG_RCV *recv_p)
const VFID * vfid
Definition: log_append.hpp:56
VFID vfid
EHID xhid
static int catalog_write_unwritten_portion(THREAD_ENTRY *thread_p, CATALOG_RECORD *catalog_record_p, PGSLOTID *remembered_slot_id_p, int format_size)
#define ER_OBJ_INDEX_NOT_FOUND
Definition: error_code.h:877
static int success()
void init(lf_tran_system &transys, int entry_idx, int hash_size, int freelist_block_size, int freelist_block_count, lf_entry_descriptor &edesc)
#define CATALOG_GET_REPR_ITEM_PAGEID_PAGEID(ptr)
void log_append_undoredo_recdes2(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, const VFID *vfid, PAGE_PTR pgptr, PGLENGTH offset, const RECDES *undo_recdes, const RECDES *redo_recdes)
Definition: log_manager.c:2441
#define BTID_SET_NULL(btid)
LC_FIND_CLASSNAME
PAGE_PTR pgptr
Definition: log_append.hpp:57
#define err(fd,...)
Definition: porting.h:431
static int catalog_read_unread_portion(THREAD_ENTRY *thread_p, CATALOG_RECORD *catalog_record_p, int format_size)
#define ER_PB_BAD_PAGEID
Definition: error_code.h:67
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
#define OR_PUT_BTID(ptr, btid)
int catalog_drop_old_representations(THREAD_ENTRY *thread_p, OID *class_id_p)
void catalog_finalize(void)
#define pgbuf_fix(thread_p, vpid, fetch_mode, requestmode, condition)
Definition: page_buffer.h:255
int catalog_get_dir_oid_from_cache(THREAD_ENTRY *thread_p, const OID *class_id_p, OID *dir_oid_p)
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
void or_init(OR_BUF *buf, char *data, int length)
LF_TRAN_SYSTEM catalog_Ts
Definition: lock_free.c:49
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
struct disk_attribute * fixed
static DISK_ISVALID catalog_check_class_consistency(THREAD_ENTRY *thread_p, OID *class_oid)
#define CATALOG_CLS_INFO_SIZE
#define OR_PUT_SHORT(ptr, val)
#define CATALOG_GET_REPR_ITEM_REPRID(ptr)
#define CATALOG_CLS_INFO_TOT_PAGES_OFF
#define CATALOG_GET_BT_STATS_BTID(var, ptr)
static PAGE_PTR catalog_get_representation_record_after_search(THREAD_ENTRY *thread_p, OID *class_id_p, RECDES *record_p, PGBUF_LATCH_MODE latch, int is_peek, OID *rep_dir_p, int *out_repr_count_p, bool lookup_hash)
OR_CLASSREP * heap_classrepr_get(THREAD_ENTRY *thread_p, const OID *class_oid, RECDES *class_recdes, REPR_ID reprid, int *idx_incache)
Definition: heap_file.c:2299
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
#define ER_QPROC_FUNCTION_ARG_ERROR
Definition: error_code.h:1170
void pgbuf_get_vpid(PAGE_PTR pgptr, VPID *vpid)
Definition: page_buffer.c:4579
offset_type offset
Definition: log_append.hpp:58
#define pthread_mutex_lock(a)
void * ehash_delete(THREAD_ENTRY *thread_p, EHID *ehid_p, void *key_p)
static int rv
#define VFID_COPY(vfid_ptr1, vfid_ptr2)
Definition: file_manager.h:69
static void catalog_get_repr_item_from_record(CATALOG_REPR_ITEM *item_p, char *rec_p)
void log_sysop_abort(THREAD_ENTRY *thread_p)
Definition: log_manager.c:4017
#define NULL_REPRID
#define CATALOG_CLS_INFO_TIME_STAMP_OFF
static char * catalog_find_representation_item_position(INT16 repr_id, int repr_cnt, char *repr_p, int *out_position_p)
static void error(const char *msg)
Definition: gencat.c:331
#define VPID_ISNULL(vpid_ptr)
Definition: dbtype_def.h:925
const char * data
Definition: recovery.h:203
void log_append_undo_recdes2(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, const VFID *vfid, PAGE_PTR pgptr, PGLENGTH offset, const RECDES *recdes)
Definition: log_manager.c:2538
#define CATALOG_DIR_REPR_KEY
int heap_get_btid_from_index_name(THREAD_ENTRY *thread_p, const OID *p_class_oid, const char *index_name, BTID *p_found_btid)
Definition: heap_file.c:16938
PGSLOTID spage_delete(THREAD_ENTRY *thread_p, PAGE_PTR page_p, PGSLOTID slot_id)
static pthread_mutex_t catalog_Max_space_lock
#define HFID_IS_NULL(hfid)
int catalog_get_last_representation_id(THREAD_ENTRY *thread_p, OID *class_oid_p, REPR_ID *repr_id_p)
char * or_class_name(RECDES *record)
static int catalog_entry_uninit(void *ent)
int catalog_rv_new_page_redo(THREAD_ENTRY *thread_p, LOG_RCV *recv_p)
#define ER_SP_UNKNOWN_SLOTID
Definition: error_code.h:99
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define CLS_INFO_INITIALIZER
static const bool COPY
static void catalog_clear_hash_table(THREAD_ENTRY *thread_p)
static int catalog_get_key_list(THREAD_ENTRY *thread_p, void *key, void *val, void *args)
static int catalog_store_attribute_value(THREAD_ENTRY *thread_p, void *value, int length, CATALOG_RECORD *ct_recordp, PGSLOTID *remembered_slotid)
INT16 PGLENGTH
#define OR_PUT_HFID(ptr, hfid)
CTID * catalog_create(THREAD_ENTRY *thread_p, CTID *catalog_id_p)
#define OR_GET_INT(ptr)
INT16 PGSLOTID
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
static unsigned int catalog_key_hash(void *key, int htsize)
void catalog_free_class_info(CLS_INFO *class_info_p)
#define DB_PAGESIZE
#define ER_HEAP_UNKNOWN_OBJECT
Definition: error_code.h:102
void recdes_free_data_area(RECDES *rec)
void pgbuf_set_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, PAGE_TYPE ptype)
Definition: page_buffer.c:4847
static void catalog_put_disk_attribute(char *rec_p, DISK_ATTR *attr_p)
static bool catalog_is_header_initialized
#define OR_PUT_INT(ptr, val)
#define CATALOG_REPR_ITEM_COUNT_OFF
int catalog_get_cardinality(THREAD_ENTRY *thread_p, OID *class_oid, DISK_REPR *rep, BTID *btid, const int key_pos, int *cardinality)
#define CATALOG_REPR_ITEM_INITIALIZER
void er_clear(void)
#define CATALOG_PUT_PGHEADER_OVFL_PGID_PAGEID(ptr, val)
void log_sysop_attach_to_outer(THREAD_ENTRY *thread_p)
Definition: log_manager.c:4076
void log_sysop_commit(THREAD_ENTRY *thread_p)
Definition: log_manager.c:3895
static int catalog_initialize_new_page(THREAD_ENTRY *thread_p, PAGE_PTR page, void *args)
#define CATALOG_BT_STATS_LEAFS_OFF
#define CATALOG_BT_STATS_BTID_OFF
static int catalog_adjust_directory_count(THREAD_ENTRY *thread_p, PAGE_PTR page_p, RECDES *record_p, int delta)
int REPR_ID
CATALOG_ENTRY * stack
int i
Definition: dynamic_load.c:954
int has_function
Definition: statistics.h:64
static LF_ENTRY_DESCRIPTOR catalog_entry_Descriptor
static int catalog_key_copy(void *src, void *dest)
static int catalog_insert_representation_item(THREAD_ENTRY *thread_p, RECDES *record_p, OID *rep_dir_p)
#define CATALOG_GET_REPR_ITEM_PAGEID_VOLID(ptr)
static int catalog_drop_representation_helper(THREAD_ENTRY *thread_p, PAGE_PTR page_p, VPID *page_id_p, PGSLOTID slot_id)
INT16 type
int catalog_get_cardinality_by_name(THREAD_ENTRY *thread_p, const char *class_name, const char *index_name, const int key_pos, int *cardinality)
#define CATALOG_DISK_ATTR_ID_OFF
#define NULL_VOLID
#define SP_ERROR
Definition: slotted_page.h:49
#define BTID_IS_NULL(btid)
CLS_INFO * orc_class_info_from_record(RECDES *record)
#define catalog_free_class_info_and_init(class_info_p)
static int catalog_entry_init(void *ent)
short volid
Definition: dbtype_def.h:887
static PGLENGTH catalog_Max_record_size
static void catalog_copy_disk_attributes(DISK_ATTR *new_attrs_p, int new_attr_count, DISK_ATTR *pre_attrs_p, int pre_attr_count)
INT32 PAGEID
#define OID_ISNULL(oidp)
Definition: oid.h:81
#define CATALOG_DISK_ATTR_LOCATION_OFF
#define DONT_FREE
Definition: page_buffer.h:41
#define CATALOG_DISK_ATTR_TYPE_OFF
static int catalog_store_btree_statistics(THREAD_ENTRY *thread_p, BTREE_STATS *bt_statsp, CATALOG_RECORD *ct_recordp, PGSLOTID *remembered_slotid)
void clear(cubthread::entry *thread_p)
static catalog_hashmap_type catalog_Hashmap
SCAN_CODE heap_next(THREAD_ENTRY *thread_p, const HFID *hfid, OID *class_oid, OID *next_oid, RECDES *recdes, HEAP_SCANCACHE *scan_cache, int ispeeking)
Definition: heap_file.c:18622
int recdes_allocate_data_area(RECDES *rec, int size)
static int catalog_store_disk_representation(THREAD_ENTRY *thread_p, DISK_REPR *disk_reprp, CATALOG_RECORD *ct_recordp, PGSLOTID *remembered_slotid)
static void catalog_dump_representation(DISK_REPR *dr)
static int catalog_fetch_disk_attribute(THREAD_ENTRY *thread_p, DISK_ATTR *disk_attrp, CATALOG_RECORD *ct_recordp)
static void catalog_initialize_max_space(CATALOG_MAX_SPACE *header_p)
#define SP_DOESNT_FIT
Definition: slotted_page.h:51
static int catalog_drop_representation_item(THREAD_ENTRY *thread_p, OID *class_id, CATALOG_REPR_ITEM *repr_item)
#define CATALOG_BT_STATS_SIZE
static int catalog_key_compare(void *key1, void *key2)
int heap_get_class_name(THREAD_ENTRY *thread_p, const OID *class_oid, char **class_name)
Definition: heap_file.c:9328
#define ER_CT_INVALID_CLASSID
Definition: error_code.h:492
#define ER_CT_MISSING_REPR_DIR
Definition: error_code.h:498
#define PEEK
Definition: file_io.h:74
#define VPID_SET_NULL(vpid_ptr)
Definition: dbtype_def.h:906
#define CATALOG_GET_PGHEADER_OVFL_PGID_VOLID(ptr)
static int catalog_file_map_find_optimal_page(THREAD_ENTRY *thread_p, PAGE_PTR *page, bool *stop, void *args)
CTID catalog_Id
HFID ci_hfid
static int catalog_get_record_from_page(THREAD_ENTRY *thread_p, CATALOG_RECORD *ct_recordp)
int class_id
Definition: load_common.hpp:40
const char ** p
Definition: dynamic_load.c:945
#define catalog_free_representation_and_init(repr_p)
static PAGE_PTR catalog_get_new_page(THREAD_ENTRY *thread_p, VPID *page_id, bool is_overflow_page)
PAGEID hpgid
struct tp_domain * or_get_domain(OR_BUF *buf, struct tp_domain *dom, int *is_null)
#define CATALOG_MAX_SLOT_ID_SIZE
static int catalog_fetch_btree_statistics(THREAD_ENTRY *thread_p, BTREE_STATS *bt_statsp, CATALOG_RECORD *ct_recordp)
DISK_ISVALID
Definition: disk_manager.h:53
DISK_ISVALID catalog_check_consistency(THREAD_ENTRY *thread_p)
#define OR_GET_SHORT(ptr)
#define CATALOG_PUT_PGHEADER_PG_OVFL(ptr, val)
#define CATALOG_GET_PGHEADER_PG_OVFL(ptr)
#define CATALOG_DISK_ATTR_SIZE
#define CATALOG_REPR_ITEM_SIZE
#define OR_PUT_BYTE(ptr, val)
int spage_insert_for_recovery(THREAD_ENTRY *thread_p, PAGE_PTR page_p, PGSLOTID slot_id, RECDES *record_descriptor_p)
const BTREE_STATS * stats_find_inherited_index_stats(OR_CLASSREP *cls_rep, OR_CLASSREP *subcls_rep, DISK_ATTR *subcls_attr, BTID *cls_btid)
int file_map_pages(THREAD_ENTRY *thread_p, const VFID *vfid, PGBUF_LATCH_MODE latch_mode, PGBUF_LATCH_CONDITION latch_cond, FILE_MAP_PAGE_FUNC func, void *args)
static int catalog_drop_directory(THREAD_ENTRY *thread_p, PAGE_PTR page_p, RECDES *record_p, OID *oid_p, OID *class_id_p)
SCAN_CODE heap_get_class_record(THREAD_ENTRY *thread_p, const OID *class_oid, RECDES *recdes_p, HEAP_SCANCACHE *scan_cache, int ispeeking)
Definition: heap_file.c:24780
static PAGE_PTR catalog_get_representation_record(THREAD_ENTRY *thread_p, OID *rep_dir_p, RECDES *record_p, PGBUF_LATCH_MODE latch, int is_peek, int *out_repr_count_p)
DISK_REPR * catalog_get_representation(THREAD_ENTRY *thread_p, OID *class_id_p, REPR_ID repr_id, CATALOG_ACCESS_INFO *catalog_access_info_p)
static int catalog_get_rep_dir(THREAD_ENTRY *thread_p, OID *class_oid_p, OID *rep_dir_p, bool lookup_hash)