CUBRID Engine  latest
unload_object.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  * unload_object.c: Utility that emits database object definitions in database
21  * object loader format.
22  */
23 
24 #ident "$Id$"
25 
26 #include "config.h"
27 
28 #include <stdio.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <signal.h>
32 #include <ctype.h>
33 #include <assert.h>
34 
35 #include <sys/stat.h>
36 #if defined(WINDOWS)
37 #include <sys/timeb.h>
38 #include <time.h>
39 #include <direct.h>
40 #define SIGALRM 14
41 #endif /* WINDOWS */
42 
43 #include "authenticate.h"
44 #include "utility.h"
45 #include "load_object.h"
46 #include "log_lsa.hpp"
47 #include "file_hash.h"
48 #include "db.h"
49 #include "memory_hash.h"
50 #include "memory_alloc.h"
51 #include "locator_cl.h"
52 #include "schema_manager.h"
53 #include "locator.h"
54 #include "transform_cl.h"
55 #include "object_accessor.h"
56 #include "object_primitive.h"
57 #include "object_representation.h"
58 #include "set_object.h"
59 
60 #include "message_catalog.h"
61 #include "server_interface.h"
62 #include "porting.h"
63 #include "unloaddb.h"
64 
65 #include "system_parameter.h"
66 #include "transform.h"
67 #include "execute_schema.h"
68 #include "network_interface_cl.h"
69 #include "transaction_cl.h"
70 #include "dbtype.h"
71 
72 #define MARK_CLASS_REQUESTED(cl_no) \
73  (class_requested[cl_no / 8] |= 1 << cl_no % 8)
74 #define MARK_CLASS_REFERENCED(cl_no) \
75  (class_referenced[cl_no / 8] |= 1 << cl_no % 8)
76 #define MARK_CLASS_PROCESSED(cl_no) \
77  (class_processed[cl_no / 8] |= 1 << cl_no % 8)
78 #define IS_CLASS_REQUESTED(cl_no) \
79  (class_requested[cl_no / 8] & 1 << cl_no % 8)
80 #define IS_CLASS_REFERENCED(cl_no) \
81  (class_referenced[cl_no / 8] & 1 << cl_no % 8)
82 #define IS_CLASS_PROCESSED(cl_no) \
83  (class_processed[cl_no / 8] & 1 << cl_no % 8)
84 
85 #define GAUGE_INTERVAL 1
86 
87 static char *output_filename = NULL;
88 
89 static int output_number = 0;
90 
93 
94 static char *class_requested = NULL;
95 static char *class_referenced = NULL;
96 static char *class_processed = NULL;
97 
98 static OID null_oid;
99 
100 static const char *prohibited_classes[] = {
101  "db_authorizations", /* old name for db_root */
102  "db_root",
103  "db_user",
104  "db_authorization",
105  "db_password",
106  "db_trigger",
107  "db_serial",
108  "db_ha_apply_info",
109  /* catalog classes */
118  CT_RESOLUTION_NAME, /* currently, not implemented */
128  CT_DUAL_NAME,
129  /* catalog vclasses */
148  NULL
149 };
150 
151 static int64_t class_objects = 0;
152 static int64_t total_objects = 0;
153 static int failed_objects = 0;
154 
155 static int64_t approximate_class_objects = 0;
156 static char *gauge_class_name;
158 
159 
160 #define OBJECT_SUFFIX "_objects"
161 
162 #define HEADER_FORMAT "-------------------------------+--------------------------------\n"" %-25s | %23s \n""-------------------------------+--------------------------------\n"
163 #define MSG_FORMAT " %-25s | %10ld (%3d%% / %5d%%)"
164 static FILE *unloadlog_file = NULL;
165 
166 
167 static int get_estimated_objs (HFID * hfid, int64_t * est_objects);
168 static int set_referenced_subclasses (DB_OBJECT * class_);
169 static bool check_referenced_domain (DB_DOMAIN * dom_list, bool set_cls_ref, int *num_cls_refp);
170 static void extractobjects_cleanup (void);
171 static void extractobjects_term_handler (int sig);
172 static bool mark_referenced_domain (SM_CLASS * class_ptr, int *num_set);
173 static void gauge_alarm_handler (int sig);
174 static int process_class (int cl_no);
175 static int process_object (DESC_OBJ * desc_obj, OID * obj_oid, int referenced_class);
176 static int process_set (DB_SET * set);
177 static int process_value (DB_VALUE * value);
178 static void update_hash (OID * object_oid, OID * class_oid, int *data);
179 static DB_OBJECT *is_class (OID * obj_oid, OID * class_oid);
180 static int all_classes_processed (void);
181 
182 /*
183  * get_estimated_objs - get the estimated number of object reside in file heap
184  * return: NO_ERROR if success, error code otherwise
185  * hfid(in): file heap id
186  * est_objects(out): estimated number of object
187  */
188 static int
189 get_estimated_objs (HFID * hfid, int64_t * est_objects)
190 {
191  int ignore_npages;
192  int nobjs = 0;
193  int error = NO_ERROR;
194 
195  error = heap_get_class_num_objects_pages (hfid, 1, &nobjs, &ignore_npages);
196  if (error < 0)
197  return error;
198 
199  *est_objects += nobjs;
200 
201  return 0;
202 }
203 
204 /*
205  * set_referenced_subclasses - set class as referenced
206  * return: NO_ERROR, if successful, error number, if not successful.
207  * class(in): root class
208  * Note:
209  * CURRENTLY, ALWAYS RETURN NO_ERROR
210  */
211 static int
213 {
214  int error = NO_ERROR;
215  int *cls_no_ptr;
216  SM_CLASS *class_ptr;
217  DB_OBJLIST *u;
218  bool check_reference_chain = false;
219  int num_set;
220  int error_code;
221 
222  error_code = fh_get (cl_table, ws_oid (class_), (FH_DATA *) (&cls_no_ptr));
223  if (error_code == NO_ERROR && cls_no_ptr != NULL)
224  {
225  if (input_filename)
226  {
227  if (include_references || is_req_class (class_))
228  {
229  if (!IS_CLASS_REFERENCED (*cls_no_ptr) && !IS_CLASS_REQUESTED (*cls_no_ptr))
230  {
231  check_reference_chain = true;
232  }
233  MARK_CLASS_REFERENCED (*cls_no_ptr);
234  }
235  }
236  else
237  {
238  if (!IS_CLASS_REFERENCED (*cls_no_ptr) && !IS_CLASS_REQUESTED (*cls_no_ptr))
239  {
240  check_reference_chain = true;
241  }
242  MARK_CLASS_REFERENCED (*cls_no_ptr);
243  }
244  }
245  else
246  {
247 #if defined(CUBRID_DEBUG)
248  fprintf (stdout, "cls_no_ptr is NULL\n");
249 #endif /* CUBRID_DEBUG */
250  }
251 
252  ws_find (class_, (MOBJ *) (&class_ptr));
253  if (class_ptr == NULL)
254  {
255  goto exit_on_error;
256  }
257 
258  if (check_reference_chain)
259  {
260  mark_referenced_domain (class_ptr, &num_set);
261  }
262 
263  /* dive to the bottom */
264  for (u = class_ptr->users; u != NULL && error == NO_ERROR; u = u->next)
265  {
266  error = set_referenced_subclasses (u->op);
267  }
268 
269 exit_on_end:
270  return error;
271 
272 exit_on_error:
273  CHECK_EXIT_ERROR (error);
274  goto exit_on_end;
275 }
276 
277 
278 /*
279  * check_referenced_domain - check for OBJECT domain as referenced
280  * return: true, if found referened OBJECT domain. false, if not
281  * found referenced OBJECT domain.
282  * dom_list(in): domain list of class attributes
283  * set_cls_ref(in): for true, do checking. for false, do marking
284  * num_cls_refp(out): number of referenced classes.
285  * Note:
286  * for referenced CLASS domain, mark the CLASS and set the number of
287  * referenced classes.
288  */
289 static bool
290 check_referenced_domain (DB_DOMAIN * dom_list, bool set_cls_ref, int *num_cls_refp)
291 {
292  bool found_object_dom;
293  DB_DOMAIN *dom;
294  DB_TYPE type;
295  DB_OBJECT *class_;
296 
297  found_object_dom = false; /* init */
298 
299  for (dom = dom_list; dom && !found_object_dom; dom = db_domain_next (dom))
300  {
301  type = TP_DOMAIN_TYPE (dom);
302  switch (type)
303  {
304  case DB_TYPE_OBJECT:
305  class_ = db_domain_class (dom);
306  if (class_ == NULL)
307  {
308  return true; /* found object domain */
309  }
310 
311  *num_cls_refp += 1; /* increase number of reference to class */
312 
313  if (set_cls_ref)
314  {
315  if (set_referenced_subclasses (class_) != NO_ERROR)
316  {
317  /* cause error - currently, not happened */
318  return true;
319  }
320  }
321  break;
322  case DB_TYPE_SET:
323  case DB_TYPE_MULTISET:
324  case DB_TYPE_SEQUENCE:
325  found_object_dom = check_referenced_domain (db_domain_set (dom), set_cls_ref, num_cls_refp);
326  break;
327  default:
328  break;
329  }
330  }
331  return found_object_dom;
332 }
333 
334 
335 /*
336  * extractobjects_cleanup - do cleanup task
337  * return: void
338  */
339 static void
341 {
342  if (obj_out)
343  {
344  if (obj_out->buffer != NULL)
346  if (obj_out->fp != NULL)
347  fclose (obj_out->fp);
348  }
349 
350  if (obj_table != NULL)
351  {
352  if (debug_flag)
353  {
354  fh_dump (obj_table);
355  }
356  fh_destroy (obj_table);
357  }
358  if (cl_table != NULL)
359  fh_destroy (cl_table);
360 
365  return;
366 }
367 
368 /*
369  * extractobjects_term_handler - extractobject terminate handler
370  * return: void
371  * sig(in): not used
372  */
373 static void
375 {
377  /* terminate a program */
378  _exit (1);
379 }
380 
381 /*
382  * mark_referenced_domain - mark given SM_CLASS closure
383  * return: true if no error, false otherwise
384  * class_ptr(in): SM_CLASS
385  * num_set(out): amortized marking number of SM_CLASS closure
386  */
387 static bool
388 mark_referenced_domain (SM_CLASS * class_ptr, int *num_set)
389 {
390  SM_ATTRIBUTE *attribute;
391 
392  if (class_ptr == NULL)
393  return true;
394 
395  for (attribute = class_ptr->shared; attribute != NULL; attribute = (SM_ATTRIBUTE *) attribute->header.next)
396  {
397  if (check_referenced_domain (attribute->domain, true /* do marking */ , num_set))
398  {
399  return false;
400  }
401  }
402 
403  for (attribute = class_ptr->class_attributes; attribute != NULL; attribute = (SM_ATTRIBUTE *) attribute->header.next)
404  {
405  if (check_referenced_domain (attribute->domain, true /* do marking */ , num_set))
406  {
407  return false;
408  }
409  }
410 
411  for (attribute = class_ptr->ordered_attributes; attribute; attribute = attribute->order_link)
412  {
413  if (attribute->header.name_space != ID_ATTRIBUTE)
414  {
415  continue;
416  }
417  if (check_referenced_domain (attribute->domain, true /* do marking */ , num_set))
418  {
419  return false;
420  }
421  }
422  return true;
423 }
424 
425 
426 /*
427  * extract_objects - dump the database in loader format.
428  * return: 0 for success. 1 for error
429  * exec_name(in): utility name
430  */
431 int
432 extract_objects (const char *exec_name, const char *output_dirname, const char *output_prefix)
433 {
434  int i, error;
435  HFID *hfid;
436  int64_t est_objects = 0;
437  int cache_size;
438  SM_CLASS *class_ptr;
439  const char **cptr;
440  int status = 0;
441  int num_unload_classes = 0;
442  DB_OBJECT **unload_class_table = NULL;
443  bool has_obj_ref;
444  int num_cls_ref;
445  SM_ATTRIBUTE *attribute;
446  void (*prev_intr_handler) (int sig);
447  void (*prev_term_handler) (int sig);
448 #if !defined (WINDOWS)
449  void (*prev_quit_handler) (int sig);
450 #endif
451  LOG_LSA lsa;
452  char unloadlog_filename[PATH_MAX];
453 
454  /* register new signal handlers */
455  prev_intr_handler = os_set_signal_handler (SIGINT, extractobjects_term_handler);
456  prev_term_handler = os_set_signal_handler (SIGTERM, extractobjects_term_handler);
457 #if !defined(WINDOWS)
458  prev_quit_handler = os_set_signal_handler (SIGQUIT, extractobjects_term_handler);
459 #endif
460 
461  if (cached_pages <= 0)
462  {
463  fprintf (stderr,
465  return 1;
466  }
467  if (page_size < (ssize_t) (sizeof (OID) + sizeof (int)))
468  {
469  fprintf (stderr,
471  return 1;
472  }
473 
474  /*
475  * Open output file
476  */
477  if (output_dirname == NULL)
478  output_dirname = ".";
479  if (strlen (output_dirname) > PATH_MAX - 8)
480  {
482  return 1;
483  }
484 
485  if (!datafile_per_class)
486  {
487  output_filename = (char *) malloc (PATH_MAX);
488 
489  if (output_filename == NULL)
490  {
491  return 1;
492  }
493  snprintf (output_filename, PATH_MAX - 1, "%s/%s%s", output_dirname, output_prefix, OBJECT_SUFFIX);
494 
495  obj_out->fp = fopen_ex (output_filename, "wb");
496  if (obj_out->fp == NULL)
497  {
498  fprintf (stderr, "%s: %s.\n\n", exec_name, strerror (errno));
500  return errno;
501  }
502  }
503 
504  {
505  struct stat stbuf;
506  int blksize;
507 
508  blksize = 4096; /* init */
509  if (stat (output_dirname, &stbuf) == -1)
510  {
511  ; /* nop */
512  }
513  else
514  {
515 #if defined (WINDOWS)
516  blksize = 4096;
517 #else /* !WINDOWS */
518  blksize = stbuf.st_blksize;
519 #endif /* WINDOWS */
520  }
521 
522  /*
523  * Determine the IO buffer size by specifying a multiple of the
524  * natural block size for the device.
525  * NEED FUTURE OPTIMIZATION
526  */
527  obj_out->iosize = 1024 * 1024; /* 1 Mbyte */
528  obj_out->iosize -= (obj_out->iosize % blksize);
529 
530  obj_out->buffer = (char *) malloc (obj_out->iosize);
531 
532  obj_out->ptr = obj_out->buffer; /* init */
533  obj_out->count = 0; /* init */
534  }
535 
536  /*
537  * The user indicates which classes are to be processed by
538  * using -i with a file that contains a list of classes.
539  * If the -i option is not used, it means process all classes.
540  * Thus if input_filename is null, it means process all classes.
541  * Three bit arrays are allocated to indicate whether a class
542  * is requested, is referenced or is processed. The index
543  * into these arrays is the same as the index into class_table->mops.
544  */
545  if ((unload_class_table = (DB_OBJECT **) malloc (DB_SIZEOF (void *) * class_table->num)) == NULL)
546  {
547  status = 1;
548  goto end;
549  }
550  for (i = 0; i < class_table->num; ++i)
551  {
552  unload_class_table[i] = NULL;
553  }
554  if ((class_requested = (char *) malloc ((class_table->num + 7) / 8)) == NULL)
555  {
556  status = 1;
557  goto end;
558  }
559  if ((class_referenced = (char *) malloc ((class_table->num + 7) / 8)) == NULL)
560  {
561  status = 1;
562  goto end;
563  }
564  if ((class_processed = (char *) malloc ((class_table->num + 7) / 8)) == NULL)
565  {
566  status = 1;
567  goto end;
568  }
569 
570  memset (class_requested, 0, (class_table->num + 7) / 8);
571  memset (class_referenced, 0, (class_table->num + 7) / 8);
572  memset (class_processed, 0, (class_table->num + 7) / 8);
573 
574  /*
575  * Create the class hash table
576  * Its purpose is to hash a class OID to the index into the
577  * class_table->mops array.
578  */
579  cl_table = fh_create ("class hash", 4096, 1024, 4, NULL, FH_OID_KEY, DB_SIZEOF (int), oid_hash, oid_compare_equals);
580  if (cl_table == NULL)
581  {
582  status = 1;
583  goto end;
584  }
585 
586  has_obj_ref = false; /* init */
587  num_cls_ref = 0; /* init */
588 
589  /*
590  * Total the number of objects & mark requested classes.
591  */
592 #if defined(CUBRID_DEBUG)
593  fprintf (stdout, "----- all class dump -----\n");
594 #endif /* CUBRID_DEBUG */
595  for (i = 0; i < class_table->num; i++)
596  {
597  if (WS_IS_DELETED (class_table->mops[i]) || class_table->mops[i] == sm_Root_class_mop)
598  {
599  continue;
600  }
601 
602  error = au_fetch_class (class_table->mops[i], NULL, AU_FETCH_READ, AU_SELECT);
603  if (error != NO_ERROR)
604  {
605  continue;
606  }
607 
608  ws_find (class_table->mops[i], (MOBJ *) (&class_ptr));
609  if (class_ptr == NULL)
610  {
611  status = 1;
612  goto end;
613  }
614 
615  for (cptr = prohibited_classes; *cptr; ++cptr)
616  {
617  if (strcmp (*cptr, sm_ch_name ((MOBJ) class_ptr)) == 0)
618  {
619  break;
620  }
621  }
622  if (*cptr == NULL)
623  {
624 #if defined(CUBRID_DEBUG)
625  fprintf (stdout, "%s%s%s\n", PRINT_IDENTIFIER (sm_ch_name ((MOBJ) class_ptr)));
626 #endif /* CUBRID_DEBUG */
627 
628  fh_put (cl_table, ws_oid (class_table->mops[i]), &i);
629  if (input_filename)
630  {
631  if (is_req_class (class_table->mops[i]))
632  {
634  }
635  else if (!required_class_only)
636  {
637  error = sm_is_system_class (class_table->mops[i]);
638  if (error < 0)
639  {
640  status = 1;
641  goto end;
642  }
643  if (error > 0)
644  {
646  error = NO_ERROR;
647  }
648  }
649  }
650  else
651  {
653  }
654 
656  {
657  if (text_print
658  (obj_out, NULL, 0, "%cid %s%s%s %d\n", '%', PRINT_IDENTIFIER (sm_ch_name ((MOBJ) class_ptr)),
659  i) != NO_ERROR)
660  {
661  status = 1;
662  goto end;
663  }
664  }
665 
666  if (IS_CLASS_REQUESTED (i))
667  {
668  if (!datafile_per_class)
669  {
670  if (!has_obj_ref)
671  { /* not found object domain */
672  for (attribute = class_ptr->shared; attribute != NULL;
673  attribute = (SM_ATTRIBUTE *) attribute->header.next)
674  {
675  /* false -> don't set */
676  if ((has_obj_ref = check_referenced_domain (attribute->domain, false, &num_cls_ref)) == true)
677  {
678 #if defined(CUBRID_DEBUG)
679  fprintf (stdout, "found OBJECT domain: %s%s%s->%s\n",
680  PRINT_IDENTIFIER (class_ptr->header.name), db_attribute_name (attribute));
681 #endif /* CUBRID_DEBUG */
682  break;
683  }
684  }
685  }
686 
687  if (!has_obj_ref)
688  { /* not found object domain */
689  for (attribute = class_ptr->class_attributes; attribute != NULL;
690  attribute = (SM_ATTRIBUTE *) attribute->header.next)
691  {
692  /* false -> don't set */
693  if ((has_obj_ref = check_referenced_domain (attribute->domain, false, &num_cls_ref)) == true)
694  {
695 #if defined(CUBRID_DEBUG)
696  fprintf (stdout, "found OBJECT domain: %s%s%s->%s\n",
697  PRINT_IDENTIFIER (class_ptr->header.name), db_attribute_name (attribute));
698 #endif /* CUBRID_DEBUG */
699  break;
700  }
701  }
702  }
703 
704  if (!has_obj_ref)
705  { /* not found object domain */
706  for (attribute = class_ptr->ordered_attributes; attribute; attribute = attribute->order_link)
707  {
708  if (attribute->header.name_space != ID_ATTRIBUTE)
709  {
710  continue;
711  }
712  has_obj_ref = check_referenced_domain (attribute->domain, false
713  /* don't set */ ,
714  &num_cls_ref);
715  if (has_obj_ref == true)
716  {
717 #if defined(CUBRID_DEBUG)
718  fprintf (stdout, "found OBJECT domain: %s%s%s->%s\n",
719  PRINT_IDENTIFIER (class_ptr->header.name), db_attribute_name (attribute));
720 #endif /* CUBRID_DEBUG */
721  break;
722  }
723  }
724  }
725  }
726  unload_class_table[num_unload_classes] = class_table->mops[i];
727  num_unload_classes++;
728  }
729 
730  hfid = sm_ch_heap ((MOBJ) class_ptr);
731  if (!HFID_IS_NULL (hfid))
732  {
733  if (get_estimated_objs (hfid, &est_objects) < 0)
734  {
735  status = 1;
736  goto end;
737  }
738  }
739  }
740  }
741 
742  OR_PUT_NULL_OID (&null_oid);
743 
744 #if defined(CUBRID_DEBUG)
745  fprintf (stdout, "has_obj_ref = %d, num_cls_ref = %d\n", has_obj_ref, num_cls_ref);
746 #endif /* CUBRID_DEBUG */
747 
748  if (has_obj_ref || num_cls_ref > 0)
749  { /* found any referenced domain */
750  int num_set;
751 
752  num_set = 0; /* init */
753 
754  for (i = 0; i < class_table->num; i++)
755  {
756  if (!IS_CLASS_REQUESTED (i))
757  {
758  continue;
759  }
760 
761  /* check for emptyness, but not implemented NEED FUTURE WORk */
762 
763  if (has_obj_ref)
764  {
766  continue;
767  }
768 
769  ws_find (class_table->mops[i], (MOBJ *) (&class_ptr));
770  if (class_ptr == NULL)
771  {
772  status = 1;
773  goto end;
774  }
775 
776  if (mark_referenced_domain (class_ptr, &num_set) == false)
777  {
778  status = 1;
779  goto end;
780  }
781 
782 
783  } /* for (i = 0; i < class_table->num; i++) */
784 
785  if (has_obj_ref)
786  {
787  ; /* nop */
788  }
789  else
790  {
791  if (num_cls_ref != num_set)
792  {
793 #if defined(CUBRID_DEBUG)
794  fprintf (stdout, "num_cls_ref = %d, num_set = %d\n", num_cls_ref, num_set);
795 #endif /* CUBRID_DEBUG */
796  status = 1;
797  goto end;
798  }
799  }
800  }
801 
802 #if defined(CUBRID_DEBUG)
803  {
804  int total_req_cls = 0;
805  int total_ref_cls = 0;
806 
807  fprintf (stdout, "----- referenced class dump -----\n");
808  for (i = 0; i < class_table->num; i++)
809  {
810  if (!IS_CLASS_REQUESTED (i))
811  {
812  continue;
813  }
814  total_req_cls++;
815  if (IS_CLASS_REFERENCED (i))
816  {
817  ws_find (class_table->mops[i], (MOBJ *) (&class_ptr));
818  if (class_ptr == NULL)
819  {
820  status = 1;
821  goto end;
822  }
823  fprintf (stdout, "%s%s%s\n", PRINT_IDENTIFIER (sm_ch_name ((MOBJ) class_ptr)));
824  total_ref_cls++;
825  }
826  }
827  fprintf (stdout, "class_table->num = %d, total_req_cls = %d, total_ref_cls = %d\n", class_table->num, total_req_cls,
828  total_ref_cls);
829  }
830 #endif /* CUBRID_DEBUG */
831 
832  /*
833  * Lock all unloaded classes with IS_LOCK
834  */
835  if (locator_fetch_set (num_unload_classes, unload_class_table, DB_FETCH_READ, DB_FETCH_READ, true) == NULL)
836  {
837  status = 1;
838  goto end;
839  }
840 
841  locator_get_append_lsa (&lsa);
842 
843  /*
844  * Estimate the number of objects.
845  */
846 
847  if (est_size == 0)
848  {
849  est_size = est_objects;
850  }
851 
852  cache_size = cached_pages * page_size / (DB_SIZEOF (OID) + DB_SIZEOF (int));
853  est_size = est_size > cache_size ? est_size : cache_size;
854 
855  /*
856  * Create the hash table
857  */
858  obj_table =
861 
862  if (obj_table == NULL)
863  {
864  status = 1;
865  goto end;
866  }
867 
868  /*
869  * Dump the object definitions
870  */
871  total_approximate_class_objects = est_objects;
872  snprintf (unloadlog_filename, sizeof (unloadlog_filename) - 1, "%s_unloaddb.log", output_prefix);
873  unloadlog_file = fopen (unloadlog_filename, "w+");
874  if (unloadlog_file != NULL)
875  {
876  fprintf (unloadlog_file, HEADER_FORMAT, "Class Name", "Total Instances");
877  }
878  if (verbose_flag)
879  {
880  fprintf (stdout, HEADER_FORMAT, "Class Name", "Total Instances");
881  }
882 
883  do
884  {
885  for (i = 0; i < class_table->num; i++)
886  {
887  if (!WS_IS_DELETED (class_table->mops[i]) && class_table->mops[i] != sm_Root_class_mop)
888  {
889  int ret_val;
890 
892  {
893  char outfile[PATH_MAX];
894 
895  ws_find (class_table->mops[i], (MOBJ *) (&class_ptr));
896  if (class_ptr == NULL)
897  {
898  status = 1;
899  goto end;
900  }
901 
902  snprintf (outfile, PATH_MAX - 1, "%s/%s_%s%s", output_dirname, output_prefix,
903  sm_ch_name ((MOBJ) class_ptr), OBJECT_SUFFIX);
904 
905  obj_out->fp = fopen_ex (outfile, "wb");
906  if (obj_out->fp == NULL)
907  {
908  status = 1;
909  goto end;
910  }
911  }
912 
913  ret_val = process_class (i);
914 
916  {
918  {
919  status = 1;
920  goto end;
921  }
922 
923  fclose (obj_out->fp);
924  obj_out->fp = NULL;
925  }
926 
927  if (ret_val != NO_ERROR)
928  {
929  if (!ignore_err_flag)
930  {
931  status = 1;
932  goto end;
933  }
934  }
935  }
936  }
937  }
938  while (!all_classes_processed ());
939 
940  if (failed_objects != 0)
941  {
942  status = 1;
945  if (unloadlog_file != NULL)
946  {
947  fprintf (unloadlog_file,
950  }
951  }
952  else if (verbose_flag)
953  {
955  total_objects);
956  }
957 
958  if (unloadlog_file != NULL)
959  {
960  if (failed_objects == 0)
961  {
962  fprintf (unloadlog_file,
964  total_objects);
965  }
967  lsa.pageid, lsa.offset);
968  }
969 
970  /* flush remaining buffer */
972  {
973  status = 1;
974  }
975 
976 /* in case of both normal and error */
977 end:
978  if (unloadlog_file != NULL)
979  {
980  fclose (unloadlog_file);
981  }
982  /*
983  * Cleanup
984  */
985  free_and_init (unload_class_table);
987 
988  /* restore previous signal handlers */
989  (void) os_set_signal_handler (SIGINT, prev_intr_handler);
990  (void) os_set_signal_handler (SIGTERM, prev_term_handler);
991 #if !defined (WINDOWS)
992  (void) os_set_signal_handler (SIGQUIT, prev_quit_handler);
993 #endif
994 
995  return (status);
996 }
997 
998 
999 /*
1000  * gauge_alarm_handler - signal handler
1001  * return: void
1002  * sig(in): singal number
1003  */
1004 static void
1006 {
1007  if (sig == SIGALRM)
1008  {
1009  fprintf (stdout, MSG_FORMAT "\r", gauge_class_name, class_objects,
1010  (class_objects > 0
1012  class_objects) ? (int) (100 * ((float) class_objects / (float) approximate_class_objects)) : 100,
1013  (int) (100 * ((float) total_objects / (float) total_approximate_class_objects)));
1014  fflush (stdout);
1015  }
1016  else
1017  {
1018  ;
1019  }
1020 #if !defined(WINDOWS)
1021  alarm (GAUGE_INTERVAL);
1022 #endif
1023  return;
1024 }
1025 
1026 /*
1027  * process_class - dump one class in loader format
1028  * return: NO_ERROR, if successful, error number, if not successful.
1029  * cl_no(in): class object index for class_table
1030  */
1031 static int
1032 process_class (int cl_no)
1033 {
1034  int error = NO_ERROR;
1035  DB_OBJECT *class_ = class_table->mops[cl_no];
1036  int i = 0;
1037  int v = 0;
1038  SM_CLASS *class_ptr;
1039  SM_ATTRIBUTE *attribute;
1040  LC_COPYAREA *fetch_area; /* Area where objects are received */
1041  HFID *hfid;
1042  OID *class_oid;
1043  OID last_oid;
1044  LOCK lock = IS_LOCK; /* Lock to acquire for the above purpose */
1045  int nobjects, nfetched;
1046  LC_COPYAREA_MANYOBJS *mobjs; /* Describe multiple objects in area */
1047  LC_COPYAREA_ONEOBJ *obj; /* Describe on object in area */
1048  RECDES recdes; /* Record descriptor */
1049  DESC_OBJ *desc_obj = NULL; /* The object described by obj */
1050  int requested_class = 0;
1051  int referenced_class = 0;
1052  void (*prev_handler) (int sig) = NULL;
1053  unsigned int prev_alarm = 0;
1054 #if defined(WINDOWS)
1055  struct _timeb timebuffer;
1056  time_t start = 0;
1057 #endif
1058  int total;
1059 
1060  /*
1061  * Only process classes that were requested or classes that were
1062  * referenced via requested classes.
1063  */
1064  if (IS_CLASS_PROCESSED (cl_no))
1065  {
1066  goto exit_on_end; /* do nothing successfully */
1067  }
1068 
1069  if (IS_CLASS_REQUESTED (cl_no))
1070  requested_class = 1;
1071  if (IS_CLASS_REFERENCED (cl_no))
1072  referenced_class = 1;
1073 
1074  if (!requested_class && !referenced_class)
1075  {
1076  goto exit_on_end; /* do nothing successfully */
1077  }
1078 
1079  class_objects = 0;
1080  MARK_CLASS_PROCESSED (cl_no);
1081 
1082  /* Get the class data */
1083  ws_find (class_, (MOBJ *) (&class_ptr));
1084  if (class_ptr == NULL)
1085  {
1086  goto exit_on_error;
1087  }
1088 
1089  class_oid = ws_oid (class_);
1090 
1091  v = 0;
1092  for (attribute = class_ptr->shared; attribute != NULL; attribute = (SM_ATTRIBUTE *) attribute->header.next)
1093  {
1094 
1095  if (DB_VALUE_TYPE (&attribute->default_value.value) == DB_TYPE_NULL)
1096  {
1097  continue;
1098  }
1099  if (v == 0)
1100  {
1102  (obj_out, NULL, 0, "%cclass %s%s%s shared (%s%s%s", '%',
1103  PRINT_IDENTIFIER (sm_ch_name ((MOBJ) class_ptr)),
1104  PRINT_IDENTIFIER (attribute->header.name)));
1105  }
1106  else
1107  {
1108  CHECK_PRINT_ERROR (text_print (obj_out, NULL, 0, ", %s%s%s", PRINT_IDENTIFIER (attribute->header.name)));
1109  }
1110 
1111  ++v;
1112  }
1113  if (v)
1114  {
1115  CHECK_PRINT_ERROR (text_print (obj_out, ")\n", 2, NULL));
1116  }
1117 
1118  v = 0;
1119  for (attribute = class_ptr->shared; attribute != NULL; attribute = (SM_ATTRIBUTE *) attribute->header.next)
1120  {
1121  if (DB_VALUE_TYPE (&attribute->default_value.value) == DB_TYPE_NULL)
1122  {
1123  continue;
1124  }
1125  if (v)
1126  {
1128  }
1129  error = process_value (&attribute->default_value.value);
1130  if (error != NO_ERROR)
1131  {
1132  if (!ignore_err_flag)
1133  goto exit_on_error;
1134  }
1135 
1136  ++v;
1137  }
1138  if (v)
1139  {
1140  CHECK_PRINT_ERROR (text_print (obj_out, "\n", 1, NULL));
1141  }
1142 
1143  v = 0;
1144  for (attribute = class_ptr->class_attributes; attribute != NULL; attribute = (SM_ATTRIBUTE *) attribute->header.next)
1145  {
1146  if (DB_VALUE_TYPE (&attribute->default_value.value) == DB_TYPE_NULL)
1147  {
1148  continue;
1149  }
1150  if (v == 0)
1151  {
1153  (obj_out, NULL, 0, "%cclass %s%s%s class (%s%s%s", '%',
1154  PRINT_IDENTIFIER (sm_ch_name ((MOBJ) class_ptr)),
1155  PRINT_IDENTIFIER (attribute->header.name)));
1156  }
1157  else
1158  {
1159  CHECK_PRINT_ERROR (text_print (obj_out, NULL, 0, ", %s%s%s", PRINT_IDENTIFIER (attribute->header.name)));
1160  }
1161  ++v;
1162  }
1163  if (v)
1164  {
1165  CHECK_PRINT_ERROR (text_print (obj_out, ")\n", 2, NULL));
1166  }
1167 
1168  v = 0;
1169  for (attribute = class_ptr->class_attributes; attribute != NULL; attribute = (SM_ATTRIBUTE *) attribute->header.next)
1170  {
1171 
1172  if (DB_VALUE_TYPE (&attribute->default_value.value) == DB_TYPE_NULL)
1173  {
1174  continue;
1175  }
1176  if (v)
1177  {
1179  }
1180  if ((error = process_value (&attribute->default_value.value)) != NO_ERROR)
1181  {
1182  if (!ignore_err_flag)
1183  {
1184  goto exit_on_error;
1185  }
1186  }
1187 
1188  ++v;
1189  }
1190 
1191  CHECK_PRINT_ERROR (text_print (obj_out, NULL, 0, (v) ? "\n%cclass %s%s%s (" /* new line */
1192  : "%cclass %s%s%s (", '%', PRINT_IDENTIFIER (sm_ch_name ((MOBJ) class_ptr))));
1193 
1194  v = 0;
1195  attribute = class_ptr->ordered_attributes;
1196  while (attribute)
1197  {
1198  if (attribute->header.name_space == ID_ATTRIBUTE)
1199  {
1200  CHECK_PRINT_ERROR (text_print (obj_out, NULL, 0, (v) ? " %s%s%s" /* space */
1201  : "%s%s%s", PRINT_IDENTIFIER (attribute->header.name)));
1202  ++v;
1203  }
1204  attribute = (SM_ATTRIBUTE *) attribute->order_link;
1205  }
1206  CHECK_PRINT_ERROR (text_print (obj_out, ")\n", 2, NULL));
1207 
1208  /* Find the heap where the instances are stored */
1209  hfid = sm_ch_heap ((MOBJ) class_ptr);
1210  if (hfid->vfid.fileid == NULL_FILEID)
1211  {
1213  {
1214  total = 100;
1215  }
1216  else
1217  {
1218  total = (int) (100 * ((float) total_objects / (float) total_approximate_class_objects));
1219  }
1220  fprintf (unloadlog_file, MSG_FORMAT "\n", sm_ch_name ((MOBJ) class_ptr), (long) 0, 100, total);
1221  fflush (unloadlog_file);
1222  if (verbose_flag)
1223  {
1224  fprintf (stdout, MSG_FORMAT "\n", sm_ch_name ((MOBJ) class_ptr), (long) 0, 100, total);
1225  fflush (stdout);
1226  }
1227  goto exit_on_end;
1228  }
1229 
1230  /* Flush all the instances */
1231 
1233  {
1235  {
1236  total = 100;
1237  }
1238  else
1239  {
1240  total = (int) (100 * ((float) total_objects / (float) total_approximate_class_objects));
1241  }
1242  fprintf (unloadlog_file, MSG_FORMAT "\n", sm_ch_name ((MOBJ) class_ptr), (long) 0, 100, total);
1243  fflush (unloadlog_file);
1244  if (verbose_flag)
1245  {
1246  fprintf (stdout, MSG_FORMAT "\n", sm_ch_name ((MOBJ) class_ptr), (long) 0, 100, total);
1247  fflush (stdout);
1248  }
1249  goto exit_on_end;
1250  }
1251 
1252  nobjects = 0;
1253  nfetched = -1;
1254  OID_SET_NULL (&last_oid);
1255 
1256  /* Now start fetching all the instances */
1257 
1260  {
1261  if (!ignore_err_flag)
1262  goto exit_on_error;
1263  }
1264 
1265  if (verbose_flag)
1266  {
1267  gauge_class_name = (char *) sm_ch_name ((MOBJ) class_ptr);
1268 #if !defined (WINDOWS)
1269  prev_handler = os_set_signal_handler (SIGALRM, gauge_alarm_handler);
1270  prev_alarm = alarm (GAUGE_INTERVAL);
1271 #endif
1272  }
1273 
1274  desc_obj = make_desc_obj (class_ptr);
1275 
1276  while (nobjects != nfetched)
1277  {
1278  if (locator_fetch_all
1279  (hfid, &lock, LC_FETCH_MVCC_VERSION, class_oid, &nobjects, &nfetched, &last_oid, &fetch_area) == NO_ERROR)
1280  {
1281  if (fetch_area != NULL)
1282  {
1283  mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (fetch_area);
1284  obj = LC_START_ONEOBJ_PTR_IN_COPYAREA (mobjs);
1285 
1286  for (i = 0; i < mobjs->num_objs; ++i)
1287  {
1288  /*
1289  * Process all objects for a requested class, but
1290  * only referenced objects for a referenced class.
1291  */
1292  ++class_objects;
1293  ++total_objects;
1294  LC_RECDES_TO_GET_ONEOBJ (fetch_area, obj, &recdes);
1295  if ((error = desc_disk_to_obj (class_, class_ptr, &recdes, desc_obj)) == NO_ERROR)
1296  {
1297  if ((error = process_object (desc_obj, &obj->oid, referenced_class)) != NO_ERROR)
1298  {
1299  if (!ignore_err_flag)
1300  {
1301  desc_free (desc_obj);
1302  locator_free_copy_area (fetch_area);
1303  goto exit_on_error;
1304  }
1305  }
1306  }
1307  else
1308  {
1309  if (error == ER_TF_BUFFER_UNDERFLOW)
1310  {
1311  desc_free (desc_obj);
1312  goto exit_on_error;
1313  }
1314  ++failed_objects;
1315  }
1316  obj = LC_NEXT_ONEOBJ_PTR_IN_COPYAREA (obj);
1317 #if defined(WINDOWS)
1318  if (verbose_flag && (i % 10 == 0))
1319  {
1320  _ftime (&timebuffer);
1321  if (start == 0)
1322  {
1323  start = timebuffer.time;
1324  }
1325  else
1326  {
1327  if ((timebuffer.time - start) > GAUGE_INTERVAL)
1328  {
1329  gauge_alarm_handler (SIGALRM);
1330  start = timebuffer.time;
1331  }
1332  }
1333  }
1334 #endif
1335  }
1336  locator_free_copy_area (fetch_area);
1337  }
1338  else
1339  {
1340  /* No more objects */
1341  break;
1342  }
1343  }
1344  else
1345  {
1346  /* some error was occurred */
1347  if (!ignore_err_flag)
1348  {
1349  desc_free (desc_obj);
1350  goto exit_on_error;
1351  }
1352  else
1353  ++failed_objects;
1354  }
1355  }
1356 
1357  desc_free (desc_obj);
1358 
1361  {
1362  total = 100;
1363  }
1364  else
1365  {
1366  total = (int) (100 * ((float) total_objects / (float) total_approximate_class_objects));
1367  }
1368  if (verbose_flag)
1369  {
1370 #if !defined(WINDOWS)
1371  alarm (prev_alarm);
1372  (void) os_set_signal_handler (SIGALRM, prev_handler);
1373 #endif
1374 
1375  fprintf (stdout, MSG_FORMAT "\n", sm_ch_name ((MOBJ) class_ptr), class_objects, 100, total);
1376  fflush (stdout);
1377  }
1378  fprintf (unloadlog_file, MSG_FORMAT "\n", sm_ch_name ((MOBJ) class_ptr), class_objects, 100, total);
1379 
1380 exit_on_end:
1381 
1382  return error;
1383 
1384 exit_on_error:
1385 
1386  CHECK_EXIT_ERROR (error);
1387  goto exit_on_end;
1388 
1389 }
1390 
1391 /*
1392  * process_object - dump one object in loader format
1393  * return: NO_ERROR, if successful, error number, if not successful.
1394  * desc_obj(in): object data
1395  * obj_oid(in): object oid
1396  * referenced_class(in): is referenced ?
1397  */
1398 static int
1399 process_object (DESC_OBJ * desc_obj, OID * obj_oid, int referenced_class)
1400 {
1401  int error = NO_ERROR;
1402  SM_CLASS *class_ptr;
1403  SM_ATTRIBUTE *attribute;
1404  DB_VALUE *value;
1405  OID *class_oid;
1406  int data;
1407  int v = 0;
1408 
1409  class_ptr = desc_obj->class_;
1410  class_oid = ws_oid (desc_obj->classop);
1411  if (!datafile_per_class && referenced_class)
1412  { /* need to hash OID */
1413  update_hash (obj_oid, class_oid, &data);
1414  if (debug_flag)
1415  {
1417  (obj_out, NULL, 0, "%d/*%d.%d.%d*/: ", data, obj_oid->volid, obj_oid->pageid,
1418  obj_oid->slotid));
1419  }
1420  else
1421  {
1422  CHECK_PRINT_ERROR (text_print (obj_out, NULL, 0, "%d: ", data));
1423  }
1424  }
1425 
1426  attribute = class_ptr->ordered_attributes;
1427  for (attribute = class_ptr->ordered_attributes; attribute; attribute = attribute->order_link)
1428  {
1429 
1430  if (attribute->header.name_space != ID_ATTRIBUTE)
1431  continue;
1432 
1433  if (v)
1435 
1436  value = &desc_obj->values[attribute->storage_order];
1437 
1438  if ((error = process_value (value)) != NO_ERROR)
1439  {
1440  if (!ignore_err_flag)
1441  goto exit_on_error;
1442  }
1443 
1444  ++v;
1445  }
1446  CHECK_PRINT_ERROR (text_print (obj_out, "\n", 1, NULL));
1447 
1448 exit_on_end:
1449 
1450  return error;
1451 
1452 exit_on_error:
1453 
1454  CHECK_EXIT_ERROR (error);
1455  goto exit_on_end;
1456 
1457 }
1458 
1459 /*
1460  * process_set - dump a set in loader format
1461  * return: NO_ERROR, if successful, error number, if not successful.
1462  * set(in): set
1463  * Note:
1464  * Should only get here for class and shared attributes that have
1465  * default values.
1466  */
1467 static int
1469 {
1470  int error = NO_ERROR;
1471  SET_ITERATOR *it = NULL;
1472  DB_VALUE *element_value;
1473  int check_nelem = 0;
1474 
1476 
1477  it = set_iterate (set);
1478  while ((element_value = set_iterator_value (it)) != NULL)
1479  {
1480 
1481  if ((error = process_value (element_value)) != NO_ERROR)
1482  {
1483  if (!ignore_err_flag)
1484  goto exit_on_error;
1485  }
1486 
1487  check_nelem++;
1488 
1489  if (set_iterator_next (it))
1490  {
1491  CHECK_PRINT_ERROR (text_print (obj_out, ", ", 2, NULL));
1492  if (check_nelem >= 10)
1493  { /* set New-Line for each 10th elements */
1494  CHECK_PRINT_ERROR (text_print (obj_out, "\n", 1, NULL));
1495  check_nelem -= 10;
1496  }
1497  }
1498  }
1500 
1501 exit_on_end:
1502  if (it != NULL)
1503  {
1504  set_iterator_free (it);
1505  }
1506  return error;
1507 
1508 exit_on_error:
1509 
1510  CHECK_EXIT_ERROR (error);
1511  goto exit_on_end;
1512 }
1513 
1514 
1515 /*
1516  * process_value - dump one value in loader format
1517  * return: NO_ERROR, if successful, error number, if not successful.
1518  * value(in): the value to process
1519  */
1520 static int
1522 {
1523  int error = NO_ERROR;
1524 
1525  switch (DB_VALUE_TYPE (value))
1526  {
1527  case DB_TYPE_OID:
1528  case DB_TYPE_OBJECT:
1529  {
1530  OID *ref_oid;
1531  int ref_data;
1532  OID ref_class_oid;
1533  DB_OBJECT *classop;
1534  SM_CLASS *class_ptr;
1535  int *cls_no_ptr, cls_no;
1536 
1537  if (DB_VALUE_TYPE (value) == DB_TYPE_OID)
1538  {
1539  ref_oid = db_get_oid (value);
1540  }
1541  else
1542  {
1543  ref_oid = WS_OID (db_get_object (value));
1544  }
1545 
1546  if (required_class_only || (ref_oid == (OID *) 0) || (OID_EQ (ref_oid, &null_oid)) || datafile_per_class)
1547  {
1548  CHECK_PRINT_ERROR (text_print (obj_out, "NULL", 4, NULL));
1549  break;
1550  }
1551 
1552  OID_SET_NULL (&ref_class_oid);
1553 
1554  error = locator_does_exist (ref_oid, NULL_CHN, IS_LOCK, &ref_class_oid, NULL_CHN, false, false, NULL,
1556  if (error == LC_EXIST)
1557  {
1558  classop = is_class (ref_oid, &ref_class_oid);
1559  if (classop != NULL)
1560  {
1561  ws_find (classop, (MOBJ *) (&class_ptr));
1562  if (class_ptr == NULL)
1563  {
1564  goto exit_on_error;
1565  }
1566  CHECK_PRINT_ERROR (text_print (obj_out, NULL, 0, "@%s", sm_ch_name ((MOBJ) class_ptr)));
1567  break;
1568  }
1569 
1570  /*
1571  * Lock referenced class with S_LOCK
1572  */
1573  error = NO_ERROR; /* clear */
1574  classop = is_class (&ref_class_oid, WS_OID (sm_Root_class_mop));
1575  if (classop != NULL)
1576  {
1577  if (locator_fetch_class (classop, DB_FETCH_QUERY_READ) == NULL)
1578  {
1579  error = LC_ERROR;
1580  }
1581  }
1582  else
1583  {
1584  error = LC_ERROR;
1585  }
1586  }
1587  else if (error != LC_DOESNOT_EXIST)
1588  {
1589  error = LC_ERROR;
1590  }
1591  else
1592  {
1593  CHECK_PRINT_ERROR (text_print (obj_out, "NULL", 4, NULL));
1594  break;
1595  }
1596 
1597  if (error != NO_ERROR)
1598  {
1599  if (!ignore_err_flag)
1600  {
1601  goto exit_on_error;
1602  }
1603  else
1604  {
1605  (void) text_print (obj_out, "NULL", 4, NULL);
1606  break;
1607  }
1608  }
1609 
1610  /*
1611  * Output a reference indication if all classes are being processed,
1612  * or if a class_list is being used and references are being included,
1613  * or if a class_list is being used and the referenced class is a
1614  * requested class. Otherwise, output "NULL".
1615  */
1616 
1617  /* figure out what it means for this to be NULL, I think this happens only for the reserved system classes like
1618  * db_user that are not dumped. This is a problem because trigger objects for one, like to point directly at
1619  * the user object. There will probably be others in time. */
1620  error = fh_get (cl_table, &ref_class_oid, (FH_DATA *) (&cls_no_ptr));
1621  if (error != NO_ERROR || cls_no_ptr == NULL)
1622  {
1623  CHECK_PRINT_ERROR (text_print (obj_out, "NULL", 4, NULL));
1624  }
1625  else
1626  {
1627  cls_no = *cls_no_ptr;
1629  {
1630  update_hash (ref_oid, &ref_class_oid, &ref_data);
1631  if (debug_flag)
1632  {
1633  int *temp;
1634  error = fh_get (cl_table, &ref_class_oid, (FH_DATA *) (&temp));
1635  if (error != NO_ERROR || temp == NULL)
1636  {
1637  CHECK_PRINT_ERROR (text_print (obj_out, "NULL", 4, NULL));
1638  }
1639  else
1640  {
1642  (obj_out, NULL, 0, "@%d|%d/*%d.%d.%d*/", *temp, ref_data, ref_oid->volid,
1643  ref_oid->pageid, ref_oid->slotid));
1644  }
1645  }
1646  else
1647  {
1648  int *temp;
1649  error = fh_get (cl_table, &ref_class_oid, (FH_DATA *) (&temp));
1650  if (error != NO_ERROR || temp == NULL)
1651  {
1652  CHECK_PRINT_ERROR (text_print (obj_out, "NULL", 4, NULL));
1653  }
1654  else
1655  {
1656  CHECK_PRINT_ERROR (text_print (obj_out, NULL, 0, "@%d|%d", *temp, ref_data));
1657  }
1658  }
1659  }
1660  else
1661  {
1662  CHECK_PRINT_ERROR (text_print (obj_out, "NULL", 4, NULL));
1663  }
1664  }
1665  break;
1666  }
1667 
1668  case DB_TYPE_SET:
1669  case DB_TYPE_MULTISET:
1670  case DB_TYPE_SEQUENCE:
1672  break;
1673 
1674  case DB_TYPE_BLOB:
1675  case DB_TYPE_CLOB:
1676  {
1677  DB_ELO *elo;
1678  DB_TYPE dt = db_value_type (value);
1679  char dts;
1680 
1681  if (dt == DB_TYPE_BLOB)
1682  {
1683  dts = 'B';
1684  }
1685  else
1686  {
1687  dts = 'C';
1688  }
1689 
1690  elo = db_get_elo (value);
1691 
1692  if (elo != NULL)
1693  {
1694  if (elo->type == ELO_FBO)
1695  {
1697  (obj_out, NULL, 0, "^E'%c%lld|%s|%s'", dts, elo->size, elo->locator,
1698  elo->meta_data != NULL ? elo->meta_data : ""));
1699  }
1700  else
1701  {
1702  /* should not happen */
1703  assert (0);
1704  }
1705  }
1706  else
1707  {
1708  CHECK_PRINT_ERROR (text_print (obj_out, "NULL", 4, NULL));
1709  }
1710  break;
1711  }
1712 
1713  default:
1715  break;
1716  }
1717 
1718 exit_on_end:
1719 
1720  return error;
1721 
1722 exit_on_error:
1723 
1724  CHECK_EXIT_ERROR (error);
1725  goto exit_on_end;
1726 
1727 }
1728 
1729 
1730 /*
1731  * update_hash - update obj_table hash
1732  * return: void
1733  * object_oid(in): the object oid used as hash key
1734  * class_oid(in): the oid of the object's class
1735  * data(out): the value to associate with the oid
1736  * Note:
1737  * If the object oid exists, return the data. Otherwise, get the value for
1738  * the class oid, increment it and use it for the data. Store the data
1739  * with the object oid and class oid. The data for the class id is the
1740  * next number to use for the class. If the class oid doesn't exist,
1741  * initialize the data to 1.
1742  */
1743 static void
1744 update_hash (OID * object_oid, OID * class_oid, int *data)
1745 {
1746  int *d;
1747  int error;
1748 
1749  error = fh_get (obj_table, object_oid, (FH_DATA *) (&d));
1750  if (error != NO_ERROR || d == NULL)
1751  {
1752  error = fh_get (obj_table, class_oid, (FH_DATA *) (&d));
1753  if (error != NO_ERROR || d == NULL)
1754  {
1755  *data = 1;
1756  }
1757  else
1758  {
1759  *data = *d + 1;
1760  }
1761  if (fh_put (obj_table, class_oid, data) != NO_ERROR)
1762  {
1763  perror ("SYSTEM ERROR related with hash-file\n==>unloaddb is NOT completed");
1764  exit (1);
1765  }
1766  if (fh_put (obj_table, object_oid, data) != NO_ERROR)
1767  {
1768  perror ("SYSTEM ERROR related with hash-file\n==>unloaddb is NOT completed");
1769  exit (1);
1770  }
1771  }
1772  else
1773  {
1774  *data = *d;
1775  }
1776 }
1777 
1778 
1779 /*
1780  * is_class - determine whether the object is actually a class.
1781  * return: MOP for the object
1782  * obj_oid(in): the object oid
1783  * class_oid(in): the class oid
1784  */
1785 static DB_OBJECT *
1786 is_class (OID * obj_oid, OID * class_oid)
1787 {
1788  if (OID_EQ (class_oid, WS_OID (sm_Root_class_mop)))
1789  {
1790  return ws_mop (obj_oid, NULL);
1791  }
1792  return 0;
1793 }
1794 
1795 
1796 /*
1797  * is_req_class - determine whether the class was requested in the input file
1798  * return: 1 if true, otherwise 0.
1799  * class(in): the class object
1800  */
1801 int
1803 {
1804  int n;
1805 
1806  for (n = 0; n < class_table->num; ++n)
1807  {
1808  if (req_class_table[n] == class_)
1809  return 1;
1810  }
1811  return 0;
1812 }
1813 
1814 
1815 /*
1816  * all_classes_processed - compares class_requested with class_processed.
1817  * return: 1 if true, otherwise 0.
1818  */
1819 static int
1821 {
1822  int n;
1823 
1824  for (n = 0; n < (class_table->num + 7) / 8; ++n)
1825  {
1826  if ((class_requested[n] | class_referenced[n]) != class_processed[n])
1827  return 0;
1828  }
1829  return 1;
1830 }
1831 
1832 /*
1833  * ltrim - trim a given string.
1834  * return: pointer to the trimed string.
1835  */
1836 static char *
1837 ltrim (char *s)
1838 {
1839  char *begin;
1840 
1841  assert (s != NULL);
1842 
1843  begin = s;
1844  while (*begin != '\0')
1845  {
1846  if (isspace (*begin))
1847  {
1848  begin++;
1849  }
1850  else
1851  {
1852  break;
1853  }
1854  }
1855  s = begin;
1856 
1857  return s;
1858 }
1859 
1860 /*
1861  * get_requested_classes - read the class names from input_filename
1862  * return: 0 for success, non-zero otherwise
1863  * input_filename(in): the name of the input_file
1864  * class_list(out): the class table to store classes in
1865  */
1866 int
1867 get_requested_classes (const char *input_filename, DB_OBJECT * class_list[])
1868 {
1869  int i, j, is_partition = 0, error;
1870  int len_clsname = 0;
1871  FILE *input_file;
1872  char buffer[DB_MAX_IDENTIFIER_LENGTH];
1873  char class_name[DB_MAX_IDENTIFIER_LENGTH];
1874  char downcase_class_name[SM_MAX_IDENTIFIER_LENGTH];
1875  MOP *sub_partitions = NULL;
1876  char scan_format[16];
1877  char *trimmed_buf;
1878 
1879  if (input_filename == NULL)
1880  {
1881  return 0;
1882  }
1883 
1884  input_file = fopen (input_filename, "r");
1885  if (input_file == NULL)
1886  {
1887  perror (input_filename);
1888  return 1;
1889  }
1890  snprintf (scan_format, sizeof (scan_format), "%%%ds\n", (int) (sizeof (buffer) - 1));
1891  i = 0;
1892  while (fgets ((char *) buffer, DB_MAX_IDENTIFIER_LENGTH, input_file) != NULL)
1893  {
1894  DB_OBJECT *class_;
1895 
1896  /* trim left */
1897  trimmed_buf = ltrim (buffer);
1898  len_clsname = (int) strlen (trimmed_buf);
1899 
1900  /* get rid of \n at end of line */
1901  if (len_clsname > 0 && trimmed_buf[len_clsname - 1] == '\n')
1902  {
1903  trimmed_buf[len_clsname - 1] = 0;
1904  len_clsname--;
1905  }
1906 
1907  if (len_clsname >= 1)
1908  {
1909  sscanf ((char *) buffer, scan_format, (char *) class_name);
1910 
1911  sm_downcase_name (class_name, downcase_class_name, SM_MAX_IDENTIFIER_LENGTH);
1912 
1913  class_ = locator_find_class (downcase_class_name);
1914  if (class_ != NULL)
1915  {
1916  class_list[i] = class_;
1917  error = sm_partitioned_class_type (class_, &is_partition, NULL, &sub_partitions);
1918  if (is_partition == 1 && sub_partitions != NULL)
1919  {
1920  for (j = 0; sub_partitions[j]; j++)
1921  {
1922  i++;
1923  class_list[i] = sub_partitions[j];
1924  }
1925  }
1926  if (sub_partitions != NULL)
1927  {
1928  free_and_init (sub_partitions);
1929  }
1930  i++;
1931  }
1932  }
1933  } /* while */
1934 
1935  fclose (input_file);
1936 
1937  return 0;
1938 }
#define CT_ATTRIBUTE_NAME
Definition: transform.h:120
void fh_dump(FH_TABLE *ht)
Definition: file_hash.c:833
int get_requested_classes(const char *input_filename, DB_OBJECT *class_list[])
int locator_does_exist(OID *oidp, int chn, LOCK lock, OID *class_oid, int class_chn, int need_fetching, int prefetch, LC_COPYAREA **fetch_copyarea, LC_FETCH_VERSION_TYPE fetch_version_type)
#define HEADER_FORMAT
SM_ATTRIBUTE * shared
Definition: class_object.h:722
#define CT_DATATYPE_NAME
Definition: transform.h:131
static void update_hash(OID *object_oid, OID *class_oid, int *data)
char * hash_filename
Definition: unloaddb.c:55
#define CT_CLASSAUTH_NAME
Definition: transform.h:130
int page_size
Definition: unloaddb.c:52
#define WS_IS_DELETED(mop)
Definition: work_space.h:284
#define NO_ERROR
Definition: error_code.h:46
int heap_get_class_num_objects_pages(HFID *hfid, int approximation, int *nobjs, int *npages)
int locator_get_append_lsa(struct log_lsa *lsa)
Definition: locator_cl.c:6882
int debug_flag
Definition: unloaddb.c:56
DB_COLLECTION * db_get_set(const DB_VALUE *value)
static int process_set(DB_SET *set)
SM_CLASS * class_
Definition: load_object.h:57
int sm_is_system_class(MOP op)
#define CTV_METHFILE_NAME
Definition: transform.h:156
static FILE * unloadlog_file
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
FH_TABLE * fh_create(const char *name, int est_size, int page_size, int cached_pages, const char *hash_filename, FH_KEY_TYPE key_type, int data_size, HASH_FUNC hfun, CMP_FUNC cmpfun)
Definition: file_hash.c:164
FILE * fp
Definition: load_object.h:75
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
char * MOBJ
Definition: work_space.h:174
static void begin(char *test_name)
#define CT_METHOD_NAME
Definition: transform.h:122
MOBJ locator_fetch_set(int num_mops, MOP *mop_set, DB_FETCH_MODE inst_purpose, DB_FETCH_MODE class_purpose, int quit_on_errors)
Definition: locator_cl.c:2464
void locator_free_copy_area(LC_COPYAREA *copyarea)
Definition: locator.c:534
#define LC_DOESNOT_EXIST
DB_TYPE
Definition: dbtype_def.h:670
int text_print(TEXT_OUTPUT *tout, const char *buf, int buflen, char const *fmt,...)
Definition: load_object.c:467
#define CTV_ATTR_SD_NAME
Definition: transform.h:152
static bool check_referenced_domain(DB_DOMAIN *dom_list, bool set_cls_ref, int *num_cls_refp)
#define LC_START_ONEOBJ_PTR_IN_COPYAREA(manyobjs_ptr)
Definition: locator.h:44
void set_iterator_free(SET_ITERATOR *it)
Definition: set_object.c:4188
TP_DOMAIN * domain
Definition: class_object.h:444
DB_ELO_TYPE type
Definition: dbtype_def.h:950
#define LC_ERROR
#define CTV_DB_CHARSET_NAME
Definition: transform.h:165
static bool mark_referenced_domain(SM_CLASS *class_ptr, int *num_set)
char * output_prefix
Definition: unloaddb.c:67
#define CTV_CLASS_NAME
Definition: transform.h:148
static char * class_processed
Definition: unload_object.c:96
DESC_OBJ * make_desc_obj(SM_CLASS *class_)
Definition: load_object.c:87
static char * gauge_class_name
DB_DOMAIN * db_domain_next(const DB_DOMAIN *domain)
Definition: db_macro.c:3974
#define CT_DOMAIN_NAME
Definition: transform.h:121
#define CT_METHSIG_NAME
Definition: transform.h:123
static int output_number
Definition: unload_object.c:89
int is_req_class(DB_OBJECT *class_)
#define SM_MAX_IDENTIFIER_LENGTH
static void gauge_alarm_handler(int sig)
static int64_t class_objects
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
bool include_references
Definition: unloaddb.c:58
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
static char * output_filename
Definition: unload_object.c:87
struct sm_component * next
Definition: class_object.h:384
#define OID_SET_NULL(oidp)
Definition: oid.h:85
void sm_downcase_name(const char *name, char *buf, int maxlen)
int set_iterator_next(SET_ITERATOR *it)
Definition: set_object.c:4236
MOP locator_find_class(const char *classname)
Definition: locator_cl.c:3142
#define CTV_METHARG_SD_NAME
Definition: transform.h:155
SM_NAME_SPACE name_space
Definition: class_object.h:386
#define ER_TF_BUFFER_UNDERFLOW
Definition: error_code.h:387
#define CT_STORED_PROC_NAME
Definition: transform.h:132
#define CT_METHFILE_NAME
Definition: transform.h:125
#define CT_DUAL_NAME
Definition: transform.h:145
#define CT_CLASS_NAME
Definition: transform.h:119
const char * db_attribute_name(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1065
#define CT_PARTITION_NAME
Definition: transform.h:134
const char * output_dirname
Definition: unloaddb.c:46
char * buffer
Definition: load_object.h:67
bool datafile_per_class
Definition: unloaddb.c:61
#define IS_CLASS_REFERENCED(cl_no)
Definition: unload_object.c:80
DB_ELO * db_get_elo(const DB_VALUE *value)
static int process_object(DESC_OBJ *desc_obj, OID *obj_oid, int referenced_class)
LOCK
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
#define CT_STORED_PROC_ARGS_NAME
Definition: transform.h:133
#define LC_RECDES_TO_GET_ONEOBJ(copy_area_ptr, oneobj_ptr, recdes_ptr)
Definition: locator.h:54
Definition: db_set.h:35
const char * sm_ch_name(const MOBJ clobj)
#define assert(x)
int32_t fileid
Definition: dbtype_def.h:886
#define CTV_DB_COLLATION_NAME
Definition: transform.h:164
int desc_disk_to_obj(MOP classop, SM_CLASS *class_, RECDES *record, DESC_OBJ *obj)
Definition: load_object.c:930
#define CHECK_EXIT_ERROR(e)
Definition: load_object.h:38
#define OR_PUT_NULL_OID(ptr)
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
#define CTV_INDEX_NAME
Definition: transform.h:157
DB_TYPE db_value_type(const DB_VALUE *value)
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:725
HFID * sm_ch_heap(MOBJ clobj)
#define IS_CLASS_PROCESSED(cl_no)
Definition: unload_object.c:82
#define CTV_AUTH_NAME
Definition: transform.h:159
#define DB_MAX_IDENTIFIER_LENGTH
Definition: dbtype_def.h:495
DB_OBJECT * db_domain_class(const DB_DOMAIN *domain)
Definition: db_macro.c:4030
int fh_get(FH_TABLE *ht, FH_KEY key, FH_DATA *data)
Definition: file_hash.c:353
#define CTV_METHARG_NAME
Definition: transform.h:154
static int64_t total_objects
#define OBJECT_SUFFIX
DB_OBJECT * db_get_object(const DB_VALUE *value)
#define OID_EQ(oidp1, oidp2)
Definition: oid.h:92
VFID vfid
#define TP_DOMAIN_TYPE(dom)
static const char * prohibited_classes[]
static OID null_oid
Definition: unload_object.c:98
std::int64_t pageid
Definition: log_lsa.hpp:36
#define DB_SIZEOF(val)
Definition: memory_alloc.h:54
#define CT_INDEX_NAME
Definition: transform.h:128
#define NULL
Definition: freelistheap.h:34
#define CTV_STORED_PROC_ARGS_NAME
Definition: transform.h:162
#define LC_EXIST
char * ptr
Definition: load_object.h:69
#define GAUGE_INTERVAL
Definition: unload_object.c:85
#define CTV_TRIGGER_NAME
Definition: transform.h:160
#define CT_METHARG_NAME
Definition: transform.h:124
#define LC_NEXT_ONEOBJ_PTR_IN_COPYAREA(oneobj_ptr)
Definition: locator.h:48
#define CTV_SUPER_CLASS_NAME
Definition: transform.h:149
int extract_objects(const char *exec_name, const char *output_dirname, const char *output_prefix)
#define CHECK_PRINT_ERROR(print_fnc)
Definition: load_object.h:32
#define TM_TRAN_READ_FETCH_VERSION()
#define DONT_DECACHE
Definition: locator_cl.h:49
static int64_t total_approximate_class_objects
unsigned int oid_hash(const void *key_oid, unsigned int htsize)
Definition: oid.c:294
#define NULL_FILEID
#define CT_QUERYSPEC_NAME
Definition: transform.h:126
static int set_referenced_subclasses(DB_OBJECT *class_)
DB_VALUE * values
Definition: load_object.h:61
int desc_value_special_fprint(TEXT_OUTPUT *tout, DB_VALUE *value)
Definition: load_object.c:1575
struct db_objlist * next
Definition: dbtype_def.h:442
#define CT_COLLATION_NAME
Definition: transform.h:137
char * input_filename
Definition: unloaddb.c:47
FILE * fopen_ex(const char *filename, const char *type)
Definition: util_common.c:322
#define CTV_METHOD_NAME
Definition: transform.h:153
#define IS_CLASS_REQUESTED(cl_no)
Definition: unload_object.c:78
int oid_compare_equals(const void *key_oid1, const void *key_oid2)
Definition: oid.c:310
static int64_t approximate_class_objects
struct db_object * op
Definition: dbtype_def.h:443
static int process_value(DB_VALUE *value)
static int failed_objects
static void error(const char *msg)
Definition: gencat.c:331
MOP classop
Definition: load_object.h:56
static void extractobjects_term_handler(int sig)
void fh_destroy(FH_TABLE *ht)
Definition: file_hash.c:310
#define HFID_IS_NULL(hfid)
static char * ltrim(char *s)
#define AU_SELECT
Definition: authenticate.h:69
static int all_classes_processed(void)
#define CTV_ATTRIBUTE_NAME
Definition: transform.h:151
bool verbose_flag
Definition: unloaddb.c:57
int sm_partitioned_class_type(DB_OBJECT *classop, int *partition_type, char *keyattr, MOP **partitions)
OID * db_get_oid(const DB_VALUE *value)
#define WS_OID(mop)
Definition: work_space.h:293
static char * class_referenced
Definition: unload_object.c:95
static FH_TABLE * cl_table
Definition: unload_object.c:92
#define MARK_CLASS_PROCESSED(cl_no)
Definition: unload_object.c:76
#define PRINT_IDENTIFIER(s)
Definition: unloaddb.h:58
char * locator
Definition: dbtype_def.h:948
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
#define CTV_INDEXKEY_NAME
Definition: transform.h:158
SM_COMPONENT header
Definition: class_object.h:441
TEXT_OUTPUT * obj_out
Definition: unloaddb.c:51
static void extractobjects_cleanup(void)
int64_t est_size
Definition: unloaddb.c:54
int cached_pages
Definition: unloaddb.c:53
bool required_class_only
Definition: unloaddb.c:60
#define MSG_FORMAT
#define LC_MANYOBJS_PTR_IN_COPYAREA(copy_areaptr)
Definition: locator.h:39
int64_t size
Definition: dbtype_def.h:947
static int process_class(int cl_no)
#define CT_INDEXKEY_NAME
Definition: transform.h:129
DB_VALUE * set_iterator_value(SET_ITERATOR *it)
Definition: set_object.c:4201
int locator_fetch_all(const HFID *hfid, LOCK *lock, LC_FETCH_VERSION_TYPE fetch_version_type, OID *class_oidp, int *nobjects, int *nfetched, OID *last_oidp, LC_COPYAREA **fetch_copyarea)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
DB_OBJLIST * users
Definition: class_object.h:712
int i
Definition: dynamic_load.c:954
int locator_flush_all_instances(MOP class_mop, bool decache)
Definition: locator_cl.c:5278
#define CTV_STORED_PROC_NAME
Definition: transform.h:161
char * msgcat_message(int cat_id, int set_id, int msg_id)
int fh_put(FH_TABLE *ht, FH_KEY key, FH_DATA data)
Definition: file_hash.c:449
bool ignore_err_flag
Definition: unloaddb.c:70
const char * name
Definition: class_object.h:385
struct sm_attribute * order_link
Definition: class_object.h:461
MOP sm_Root_class_mop
_exit(1)
#define MARK_CLASS_REFERENCED(cl_no)
Definition: unload_object.c:74
void desc_free(DESC_OBJ *obj)
Definition: load_object.c:138
char * meta_data
Definition: dbtype_def.h:949
#define CT_RESOLUTION_NAME
Definition: transform.h:127
SM_ATTRIBUTE * ordered_attributes
Definition: class_object.h:753
#define CTV_PARTITION_NAME
Definition: transform.h:163
int ws_find(MOP mop, MOBJ *obj)
Definition: work_space.c:3112
static char * class_requested
Definition: unload_object.c:94
void * FH_DATA
Definition: file_hash.h:113
static int get_estimated_objs(HFID *hfid, int64_t *est_objects)
#define CTV_VCLASS_NAME
Definition: transform.h:150
DB_OBJECT ** req_class_table
Definition: unloaddb.c:63
std::int64_t offset
Definition: log_lsa.hpp:37
SIGNAL_HANDLER_FUNCTION os_set_signal_handler(const int sig_no, SIGNAL_HANDLER_FUNCTION sig_handler)
Definition: porting.c:1333
SET_ITERATOR * set_iterate(DB_COLLECTION *set)
Definition: set_object.c:4146
static FH_TABLE * obj_table
Definition: unload_object.c:91
int text_print_flush(TEXT_OUTPUT *tout)
Definition: load_object.c:442
DB_DOMAIN * db_domain_set(const DB_DOMAIN *domain)
Definition: db_macro.c:4060
#define MARK_CLASS_REQUESTED(cl_no)
Definition: unload_object.c:72
#define MSGCAT_CATALOG_UTILS
#define CT_CHARSET_NAME
Definition: transform.h:144