diff --git a/src/executables/util_admin.c b/src/executables/util_admin.c index 4b6d274c2ea..41d4b476c37 100644 --- a/src/executables/util_admin.c +++ b/src/executables/util_admin.c @@ -319,6 +319,7 @@ static UTIL_ARG_MAP ua_Diag_Option_Map[] = { {DIAG_DUMP_RECORDS_S, {ARG_BOOLEAN}, {0}}, {DIAG_OUTPUT_FILE_S, {ARG_STRING}, {0}}, {DIAG_EMERGENCY_S, {ARG_BOOLEAN}, {0}}, + {DIAG_CLASS_NAME_S, {ARG_STRING}, {0}}, {0, {0}, {0}} }; @@ -327,6 +328,7 @@ static GETOPT_LONG ua_Diag_Option[] = { {DIAG_DUMP_RECORDS_L, 0, 0, DIAG_DUMP_RECORDS_S}, {DIAG_OUTPUT_FILE_L, 1, 0, DIAG_OUTPUT_FILE_S}, {DIAG_EMERGENCY_L, 0, 0, DIAG_EMERGENCY_S}, + {DIAG_CLASS_NAME_L, 1, 0, DIAG_CLASS_NAME_S}, {0, 0, 0, 0} }; diff --git a/src/executables/util_sa.c b/src/executables/util_sa.c index d6fafe7563c..60d04cd0b16 100644 --- a/src/executables/util_sa.c +++ b/src/executables/util_sa.c @@ -1531,6 +1531,7 @@ diagdb (UTIL_FUNCTION_ARG * arg) char er_msg_file[PATH_MAX]; const char *db_name; const char *output_file = NULL; + const char *class_name; FILE *outfp = NULL; bool is_emergency = false; DIAGDUMP_TYPE diag; @@ -1565,6 +1566,7 @@ diagdb (UTIL_FUNCTION_ARG * arg) } } + class_name = utility_get_option_string_value (arg_map, DIAG_CLASS_NAME_S, 0); diag = (DIAGDUMP_TYPE) utility_get_option_int_value (arg_map, DIAG_DUMP_TYPE_S); if (diag != DIAGDUMP_LOG && utility_get_option_string_table_size (arg_map) != 1) @@ -1572,6 +1574,11 @@ diagdb (UTIL_FUNCTION_ARG * arg) goto print_diag_usage; } + if (diag != DIAGDUMP_HEAP && class_name != NULL) + { + goto print_diag_usage; + } + if (check_database_name (db_name)) { goto error_exit; @@ -1716,10 +1723,25 @@ diagdb (UTIL_FUNCTION_ARG * arg) if (diag == DIAGDUMP_ALL || diag == DIAGDUMP_HEAP) { bool dump_records; - /* this dumps the contents of all heaps */ dump_records = utility_get_option_bool_value (arg_map, DIAG_DUMP_RECORDS_S); - fprintf (outfp, "\n*** DUMP OF ALL HEAPS ***\n"); - (void) file_tracker_dump_all_heap (thread_p, outfp, dump_records); + + if (class_name == NULL) + { + fprintf (outfp, "\n*** DUMP OF ALL HEAPS ***\n"); + (void) file_tracker_dump_all_heap (thread_p, outfp, dump_records); + } + else + { + if (!sm_check_system_class_by_name (class_name)) + { + if (utility_check_class_name (class_name) != NO_ERROR) + { + goto error_exit; + } + } + fprintf (outfp, "\n*** DUMP HEAP OF %s ***\n", class_name); + heap_dump_heap_file (thread_p, outfp, dump_records, class_name); + } } db_shutdown (); diff --git a/src/executables/utility.h b/src/executables/utility.h index bbc8e063f21..4c39f85d97c 100644 --- a/src/executables/utility.h +++ b/src/executables/utility.h @@ -1197,6 +1197,8 @@ typedef struct _ha_config #define DIAG_OUTPUT_FILE_L "output-file" #define DIAG_EMERGENCY_S 11202 #define DIAG_EMERGENCY_L "emergency" +#define DIAG_CLASS_NAME_S 'c' +#define DIAG_CLASS_NAME_L "class-name" /* patch option list */ #define PATCH_RECREATE_LOG_S 'r' diff --git a/src/storage/heap_file.c b/src/storage/heap_file.c index 10c40915cca..ae0832343bd 100644 --- a/src/storage/heap_file.c +++ b/src/storage/heap_file.c @@ -14505,6 +14505,57 @@ heap_dump (THREAD_ENTRY * thread_p, FILE * fp, HFID * hfid, bool dump_records) fprintf (fp, "\n\n*** END OF DUMP FOR HEAP FILE ***\n\n"); } +#if defined (SA_MODE) +/* + * heap_dump_heap_file () - dump a specific heap file with class name + * + * return : + * thread_p (in) : thread entry + * fp (in) : output file + * dump_records (in) : true to dump records + * class_name (in) : name of class to dump + */ +void +heap_dump_heap_file (THREAD_ENTRY * thread_p, FILE * fp, bool dump_records, const char *class_name) +{ + int error_code = NO_ERROR; + OID class_oid; + LC_FIND_CLASSNAME status; + HFID hfid; + OR_PARTITION *parts = NULL; + int parts_count = 0; + + status = xlocator_find_class_oid (thread_p, class_name, &class_oid, S_LOCK); + if (status != LC_CLASSNAME_EXIST) + { + return; + } + + error_code = heap_hfid_cache_get (thread_p, &class_oid, &hfid, NULL, NULL); + if (error_code != NO_ERROR) + { + assert (false); + return; + } + + heap_dump (thread_p, fp, &hfid, dump_records); + + error_code = heap_get_class_partitions (thread_p, &class_oid, &parts, &parts_count); + if (error_code != NO_ERROR) + { + assert (false); + return; + } + + for (int i = 1; i < parts_count; i++) + { + heap_dump (thread_p, fp, &parts[i].class_hfid, dump_records); + } + + heap_clear_partition_info (thread_p, parts, parts_count); +} +#endif + /* * heap_dump_capacity () - dump heap file capacity * diff --git a/src/storage/heap_file.h b/src/storage/heap_file.h index d6c01c70b7e..ef156a1058a 100644 --- a/src/storage/heap_file.h +++ b/src/storage/heap_file.h @@ -553,6 +553,9 @@ extern int heap_set_autoincrement_value (THREAD_ENTRY * thread_p, HEAP_CACHE_ATT HEAP_SCANCACHE * scan_cache, int *is_set); extern void heap_dump (THREAD_ENTRY * thread_p, FILE * fp, HFID * hfid, bool dump_records); +#if defined (SA_MODE) +extern void heap_dump_heap_file (THREAD_ENTRY * thread_p, FILE * fp, bool dump_records, const char *class_name); +#endif extern void heap_attrinfo_dump (THREAD_ENTRY * thread_p, FILE * fp, HEAP_CACHE_ATTRINFO * attr_info, bool dump_schema); #if defined (CUBRID_DEBUG) extern void heap_chnguess_dump (FILE * fp);