/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Programmer: John Mainzer * 3/08 * * This file contains tests for the metadata journaling * features implemented in H5C2.c and friends. */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ #include "h5test.h" #include "H5Eprivate.h" #include "H5Iprivate.h" #include "H5MMprivate.h" /* Memory management */ #include "H5MFprivate.h" #include "H5AC2private.h" #include "cache2_common.h" #include "H5Fpkg.h" #define HDF5_FILE_NAME "HDF5.file" /* global variable declarations: */ const char *FILENAMES[] = { "cache_test", "cache_journal_test", "cache_sb_test", "journal_file", NULL }; /* private function declarations: */ /* utility functions */ static void begin_trans(H5C2_t * cache_ptr, hbool_t verbose, uint64_t expected_trans_num, const char * trans_name); static void copy_file(const char * input_file, const char * output_file); static void end_trans(H5F_t * file_ptr, H5C2_t * cache_ptr, hbool_t verbose, uint64_t trans_num, const char * trans_name); static hbool_t file_exists(const char * file_path_ptr); static void flush_journal(H5C2_t * cache_ptr); static void jrnl_col_major_scan_backward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, int dirty_unprotects, uint64_t trans_num); static void jrnl_col_major_scan_forward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, int dirty_unprotects, uint64_t trans_num); static void jrnl_row_major_scan_backward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, hbool_t do_renames, hbool_t rename_to_main_addr, hbool_t do_destroys, hbool_t do_mult_ro_protects, int dirty_destroys, int dirty_unprotects, uint64_t trans_num); static void jrnl_row_major_scan_forward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, hbool_t do_renames, hbool_t rename_to_main_addr, hbool_t do_destroys, hbool_t do_mult_ro_protects, int dirty_destroys, int dirty_unprotects, uint64_t trans_num); static void open_existing_file_for_journaling(const char * hdf_file_name, const char * journal_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr); static void open_existing_file_without_journaling(const char * hdf_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr); static void setup_cache_for_journaling(const char * hdf_file_name, const char * journal_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr, hbool_t use_core_driver_if_avail); static void takedown_cache_after_journaling(hid_t file_id, const char * filename, const char * journal_filename, hbool_t use_core_driver_if_avail); static void verify_journal_contents(const char * journal_file_path_ptr, const char * expected_file_path_ptr); static void verify_journal_deleted(const char * journal_file_path_ptr); static void verify_journal_empty(const char * journal_file_path_ptr); /* test functions */ static void check_buffer_writes(void); static void write_flush_verify(H5C2_jbrb_t * struct_ptr, int size, char * data, FILE * readback); static void write_noflush_verify(H5C2_jbrb_t * struct_ptr, int size, char * data, FILE * readback, int repeats); static void check_mdj_config_block_IO(void); static void test_mdj_conf_blk_read_write_discard(H5F_t * file_ptr, const char * jrnl_file_path); static void check_superblock_extensions(void); static void check_mdjsc_callbacks(void); static herr_t test_mdjsc_callback(H5C2_mdj_config_t * config_ptr, hid_t dxpl_id, void * data_ptr); static void deregister_mdjsc_callback(H5F_t * file_ptr, H5C2_t * cache_ptr, int32_t idx); static void register_mdjsc_callback(H5F_t * file_ptr, H5C2_t * cache_ptr, H5C2_mdj_status_change_func_t fcn_ptr, void * data_ptr, int32_t * idx_ptr); static void verify_mdjsc_table_config(H5C2_t * cache_ptr, int32_t table_len, int32_t num_entries, int32_t max_idx_in_use, hbool_t * free_entries); static void verify_mdjsc_callback_deregistered(H5C2_t * cache_ptr, int32_t idx); static void verify_mdjsc_callback_registered(H5C2_t * cache_ptr, H5C2_mdj_status_change_func_t fcn_ptr, void * data_ptr, int32_t idx); static void verify_mdjsc_callback_error_rejection(void); static void verify_mdjsc_callback_execution(void); static void verify_mdjsc_callback_registration_deregistration(void); static void check_message_format(void); static void check_legal_calls(void); static void check_transaction_tracking(void); static void mdj_api_example_test(void); static void mdj_smoke_check_00(void); static void mdj_smoke_check_01(void); static void mdj_smoke_check_02(void); static void write_verify_trans_num(H5C2_jbrb_t * struct_ptr, uint64_t trans_num, uint64_t verify_val); /**************************************************************************/ /**************************************************************************/ /********************************* tests: *********************************/ /**************************************************************************/ /**************************************************************************/ /*** metadata journaling test utility functions ***/ /*------------------------------------------------------------------------- * Function: begin_trans() * * Purpose: If pass2 is true on entry, attempt to begin a transaction. * If the operation fails, or if it returns an unexpected * transaction number, set passw2 to FALSE, and set failure_mssg2 * to point to an appropriate failure message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5/15/08 * * Modifications: * *------------------------------------------------------------------------- */ static void begin_trans(H5C2_t * cache_ptr, hbool_t verbose, uint64_t expected_trans_num, const char * trans_name) { const char * fcn_name = "begin_trans()"; herr_t result; uint64_t trans_num = 0; if ( pass2 ) { result = H5C2_begin_transaction(cache_ptr, &trans_num, trans_name); if ( result < 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: H5C2_begin_transaction(%s) failed.\n", fcn_name, trans_name); } pass2 = FALSE; failure_mssg2 = "H5C2_begin_transaction() failed.\n"; } else if ( trans_num != expected_trans_num ) { if ( verbose ) { HDfprintf(stdout, "%s: actual/expected trans num = %lld/%lld.\n", fcn_name, (long long)trans_num, (long long)expected_trans_num); } pass2 = FALSE; failure_mssg2 = "begin_trans() issued unexpected trans_num.\n"; } } return; } /* begin_trans() */ /*------------------------------------------------------------------------- * Function: copy_file() * * Purpose: If pass2 is true, copy the input file to the output file. * Set pass2 to FALSE and set failure_mssg2 to point to an * appropriate error message on failure. * * Do nothing if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 5/15/08 * * Modifications: * *------------------------------------------------------------------------- */ static void copy_file(const char * input_file, const char * output_file) { const char * fcn_name = "copy_file()"; char buffer[(8 * 1024) + 1]; hbool_t verbose = FALSE; size_t cur_buf_len; const size_t max_buf_len = (8 * 1024); size_t input_len; size_t input_remainder = 0; ssize_t result; int input_file_fd = -1; int output_file_fd = -1; h5_stat_t buf; if ( pass2 ) { if ( input_file == NULL ) { failure_mssg2 = "input_file NULL on entry?!?", pass2 = FALSE; } else if ( output_file == NULL ) { failure_mssg2 = "output_file NULL on entry?!?", pass2 = FALSE; } } /* get the length of the input file */ if ( pass2 ) { if ( HDstat(input_file, &buf) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat() failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "stat() failed on journal file."; pass2 = FALSE; } else { if ( (buf.st_size) == 0 ) { failure_mssg2 = "input file empty?!?"; pass2 = FALSE; } else { input_len = (size_t)(buf.st_size); input_remainder = input_len; if ( verbose ) { HDfprintf(stdout, "%s: input_len = %d.\n", fcn_name, (int)input_len); } } } } /* open the input file */ if ( pass2 ) { if ( (input_file_fd = HDopen(input_file, O_RDONLY, 0777)) == -1 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDopen(i) failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "Can't open input file."; pass2 = FALSE; } } /* open the output file */ if ( pass2 ) { if ( (output_file_fd = HDopen(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0777)) == -1 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDopen(i) failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "Can't open output file."; pass2 = FALSE; } } while ( ( pass2 ) && ( input_remainder > 0 ) ) { if ( input_remainder > max_buf_len ) { cur_buf_len = max_buf_len; input_remainder -= max_buf_len; } else { cur_buf_len = input_remainder; input_remainder = 0; } result = HDread(input_file_fd, buffer, cur_buf_len); if ( result != (int)cur_buf_len ) { if ( verbose ) { HDfprintf(stdout, "%s: HDread() failed. result = %d, errno = %d.\n", fcn_name, (int)result, errno); } failure_mssg2 = "error reading input file."; pass2 = FALSE; } buffer[cur_buf_len] = '\0'; if ( pass2 ) { result = HDwrite(output_file_fd, buffer, cur_buf_len); if ( result != (int)cur_buf_len ) { if ( verbose ) { HDfprintf(stdout, "%s: HDwrite() failed. result = %d, errno = %d.\n", fcn_name, (int)result, errno); } failure_mssg2 = "error writing output file."; pass2 = FALSE; } } } if ( input_file_fd != -1 ) { if ( HDclose(input_file_fd) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDclose(i) failed with errno = %d.\n", fcn_name, errno); } if ( pass2 ) { failure_mssg2 = "Can't close input file."; pass2 = FALSE; } } } if ( output_file_fd != -1 ) { if ( HDclose(output_file_fd) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDclose(o) failed with errno = %d.\n", fcn_name, errno); } if ( pass2 ) { failure_mssg2 = "Can't close output file."; pass2 = FALSE; } } } return; } /* copy_file() */ /*------------------------------------------------------------------------- * Function: end_trans() * * Purpose: If pass2 is true on entry, attempt to end the current * transaction. If the operation fails, set pass2 to FALSE, * and set failure_mssg2 to point to an appropriate failure * message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5/15/08 * * Modifications: * *------------------------------------------------------------------------- */ static void end_trans(H5F_t * file_ptr, H5C2_t * cache_ptr, hbool_t verbose, uint64_t trans_num, const char * trans_name) { const char * fcn_name = "end_trans()"; herr_t result; if ( pass2 ) { result = H5C2_end_transaction(file_ptr, H5AC2_dxpl_id, cache_ptr, trans_num, trans_name); if ( result < 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: H5C2_end_transaction(%lld, \"%s\") failed.\n", fcn_name, (long long)trans_num, trans_name); } pass2 = FALSE; failure_mssg2 = "H5C2_end_transaction() failed.\n"; } } return; } /* end_trans() */ /*------------------------------------------------------------------------- * Function: file_exists() * * Purpose: If pass2 is true on entry, stat the target file, and * return TRUE if it exists, and FALSE if it does not. * * If any errors are detected in this process, set pass2 * to FALSE and set failure_mssg2 to point to an appropriate * error message. * * Do nothing and return FALSE if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5//08 * * Modifications: * *------------------------------------------------------------------------- */ static hbool_t file_exists(const char * file_path_ptr) { const char * fcn_name = "file_exists()"; hbool_t ret_val = FALSE; /* will set to TRUE if necessary */ hbool_t verbose = FALSE; h5_stat_t buf; if ( pass2 ) { if ( file_path_ptr == NULL ) { failure_mssg2 = "file_path_ptr NULL on entry?!?", pass2 = FALSE; } } if ( pass2 ) { if ( HDstat(file_path_ptr, &buf) == 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat(%s) succeeded.\n", fcn_name, file_path_ptr); } ret_val = TRUE; } else if ( errno == ENOENT ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat(%s) failed with ENOENT\n", fcn_name, file_path_ptr); } } else { if ( verbose ) { HDfprintf(stdout, "%s: HDstat() failed with unexpected errno = %d.\n", fcn_name, errno); } failure_mssg2 = "HDstat() returned unexpected value."; pass2 = FALSE; } } return(ret_val); } /* file_exists() */ /*------------------------------------------------------------------------- * Function: flush_journal() * * Purpose: If pass2 is true on entry, attempt to flush the journal. * If the operation fails, set pass2 to FALSE, and set * failure_mssg2 to point to an appropriate failure message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5/15/08 * * Modifications: * *------------------------------------------------------------------------- */ static void flush_journal(H5C2_t * cache_ptr) { if ( pass2 ) { if ( H5C2_jb__flush(&(cache_ptr->mdj_jbrb)) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush() reports failure."; } } return; } /* flush_journal() */ /*------------------------------------------------------------------------- * Function: jrnl_col_major_scan_backward2() * * Purpose: Do a sequence of inserts, protects, and unprotects * broken into a sequence of transactions while scanning * backwards through the set of entries. * * If pass2 is false on entry, do nothing. * * Note tht this function is an adaption of * col_major_scan_backward2() * * Return: void * * Programmer: John Mainzer * 5/20/08 * * Modifications: * * None. * *------------------------------------------------------------------------- */ void jrnl_col_major_scan_backward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, int dirty_unprotects, uint64_t trans_num) { const char * fcn_name = "jrnl_col_major_scan_backward2()"; H5C2_t * cache_ptr; int i; int mile_stone = 1; int32_t type; int32_t idx; int32_t local_max_index[NUMBER_OF_ENTRY_TYPES]; if ( verbose ) HDfprintf(stdout, "%s: entering.\n", fcn_name); if ( pass2 ) { cache_ptr = file_ptr->shared->cache2; HDassert( cache_ptr != NULL ); for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ ) { local_max_index[i] = MIN(max_index, max_indices2[i]); } HDassert( lag > 5 ); if ( reset_stats ) { H5C2_stats__reset(cache_ptr); } idx = local_max_index[NUMBER_OF_ENTRY_TYPES - 1] + lag; } if ( verbose ) /* 1 */ HDfprintf(stdout, "%s: point %d.\n", fcn_name, mile_stone++); while ( ( pass2 ) && ( (idx + lag) >= 0 ) ) { type = NUMBER_OF_ENTRY_TYPES - 1; trans_num++; begin_trans(cache_ptr, verbose, trans_num, "jrnl_col_major_scan_backward outer loop"); if ( verbose ) { HDfprintf(stdout, "begin trans %lld, idx = %d.\n", trans_num, idx); } while ( ( pass2 ) && ( type >= 0 ) ) { if ( verbose ) { HDfprintf(stdout, "%d:%d: ", type, idx); } if ( ( pass2 ) && ( do_inserts) && ( (idx - lag) >= 0 ) && ( (idx - lag) <= local_max_index[type] ) && ( ((idx - lag) % 3) == 0 ) && ( ! entry_in_cache2(cache_ptr, type, (idx - lag)) ) ) { if ( verbose ) HDfprintf(stdout, "(i, %d, %d) ", type, (idx - lag)); insert_entry2(file_ptr, type, (idx - lag), dirty_inserts, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( idx >= 0 ) && ( idx <= local_max_index[type] ) ) { if ( verbose ) HDfprintf(stdout, "(p, %d, %d) ", type, idx); protect_entry2(file_ptr, type, idx); } if ( ( pass2 ) && ( (idx + lag) >= 0 ) && ( (idx + lag) <= local_max_index[type] ) ) { if ( verbose ) HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag)); unprotect_entry2(file_ptr, type, idx + lag, dirty_unprotects, H5C2__NO_FLAGS_SET); } if ( verbose ) HDfprintf(stdout, "\n"); type--; } end_trans(file_ptr, cache_ptr, verbose, trans_num, "jrnl_col_major_scan_backward outer loop"); if ( verbose ) { HDfprintf(stdout, "end trans %lld, idx = %d.\n", trans_num, idx); } if ( ( verbose ) && ( ! pass2 ) ) { HDfprintf(stdout, "pass2 == FALSE, failure mssg = \"%s\".\n", failure_mssg2); } idx--; } if ( verbose ) /* 2 */ HDfprintf(stdout, "%s: point %d.\n", fcn_name, mile_stone++); if ( ( pass2 ) && ( display_stats ) ) { H5C2_stats(cache_ptr, "test cache", display_detailed_stats); } if ( verbose ) HDfprintf(stdout, "%s: exiting.\n", fcn_name); return; } /* jrnl_col_major_scan_backward2() */ /*------------------------------------------------------------------------- * Function: jrnl_col_major_scan_forward2() * * Purpose: Do a sequence of inserts, protects, and unprotects * broken into a sequence of transactions while scanning * through the set of entries. * * Note that this function is an adaption of * col_major_scan_forward2(). * * If pass2 is false on entry, do nothing. * * Return: void * * Programmer: John Mainzer * 5/20/08 * * Modifications: * * None. * *------------------------------------------------------------------------- */ void jrnl_col_major_scan_forward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, int dirty_unprotects, uint64_t trans_num) { const char * fcn_name = "jrnl_col_major_scan_forward2()"; H5C2_t * cache_ptr; int i; int32_t type; int32_t idx; int32_t local_max_index[NUMBER_OF_ENTRY_TYPES]; if ( verbose ) HDfprintf(stdout, "%s: entering.\n", fcn_name); if ( pass2 ) { cache_ptr = file_ptr->shared->cache2; HDassert( cache_ptr != NULL ); for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ ) { local_max_index[i] = MIN(max_index, max_indices2[i]); } HDassert( lag > 5 ); type = 0; if ( reset_stats ) { H5C2_stats__reset(cache_ptr); } idx = -lag; } while ( ( pass2 ) && ( (idx - lag) <= MAX_ENTRIES ) ) { type = 0; trans_num++; begin_trans(cache_ptr, verbose, trans_num, "jrnl_col_major_scan_forward outer loop"); if ( verbose ) { HDfprintf(stdout, "begin trans %lld, idx = %d.\n", trans_num, idx); } while ( ( pass2 ) && ( type < NUMBER_OF_ENTRY_TYPES ) ) { if ( verbose ) { HDfprintf(stdout, "%d:%d: ", type, idx); } if ( ( pass2 ) && ( do_inserts ) && ( (idx + lag) >= 0 ) && ( (idx + lag) <= local_max_index[type] ) && ( ((idx + lag) % 3) == 0 ) && ( ! entry_in_cache2(cache_ptr, type, (idx + lag)) ) ) { if ( verbose ) HDfprintf(stdout, "(i, %d, %d) ", type, (idx + lag)); insert_entry2(file_ptr, type, (idx + lag), dirty_inserts, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( idx >= 0 ) && ( idx <= local_max_index[type] ) ) { if ( verbose ) HDfprintf(stdout, "(p, %d, %d) ", type, idx); protect_entry2(file_ptr, type, idx); } if ( ( pass2 ) && ( (idx - lag) >= 0 ) && ( (idx - lag) <= local_max_index[type] ) ) { if ( verbose ) HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag)); unprotect_entry2(file_ptr, type, idx - lag, dirty_unprotects, H5C2__NO_FLAGS_SET); } if ( verbose ) HDfprintf(stdout, "\n"); type++; } end_trans(file_ptr, cache_ptr, verbose, trans_num, "jrnl_col_major_scan_forward outer loop"); if ( verbose ) { HDfprintf(stdout, "end trans %lld, idx = %d.\n", trans_num, idx); } if ( ( verbose ) && ( ! pass2 ) ) { HDfprintf(stdout, "pass2 == FALSE, failure mssg = \"%s\".\n", failure_mssg2); } idx++; } if ( ( pass2 ) && ( display_stats ) ) { H5C2_stats(cache_ptr, "test cache", display_detailed_stats); } return; } /* jrnl_col_major_scan_forward2() */ /*------------------------------------------------------------------------- * Function: jrnl_row_major_scan_backward2() * * Purpose: Do a sequence of inserts, protects, unprotects, renames, * destroys broken into transactions while scanning backwards * through the set of entries. * * If pass2 is false on entry, do nothing. * * Note that this function is an adaption of * row_major_scan_backward2() * * Return: void * * Programmer: John Mainzer * 5/20/08 * * Modifications: * * None. * *------------------------------------------------------------------------- */ void jrnl_row_major_scan_backward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, hbool_t do_renames, hbool_t rename_to_main_addr, hbool_t do_destroys, hbool_t do_mult_ro_protects, int dirty_destroys, int dirty_unprotects, uint64_t trans_num) { const char * fcn_name = "jrnl_row_major_scan_backward2"; H5C2_t * cache_ptr; int32_t type; int32_t idx; int32_t local_max_index; int32_t lower_bound; int32_t upper_bound; if ( verbose ) HDfprintf(stdout, "%s(): Entering.\n", fcn_name); if ( pass2 ) { cache_ptr = file_ptr->shared->cache2; HDassert( cache_ptr != NULL ); HDassert( lag >= 10 ); if ( reset_stats ) { H5C2_stats__reset(cache_ptr); } } type = NUMBER_OF_ENTRY_TYPES - 1; while ( ( pass2 ) && ( type >= 0 ) ) { local_max_index = MIN(max_index, max_indices2[type]); idx = local_max_index + lag; upper_bound = local_max_index; lower_bound = upper_bound - 8; while ( ( pass2 ) && ( idx >= -lag ) ) { if ( idx == ( upper_bound + lag ) ) { trans_num++; begin_trans(cache_ptr, verbose, trans_num, "jrnl_row_major_scan_backward inner loop"); if ( verbose ) HDfprintf(stdout, "begin trans %lld.\n", (long long)trans_num); if ( verbose ) HDfprintf(stdout, "(%d, %d)\n", lower_bound, upper_bound); } while ( ( pass2 ) && ( idx >= lower_bound - lag ) ) { if ( verbose ) { HDfprintf(stdout, "%lld:%d:%d: ", trans_num, type, idx); } if ( ( pass2 ) && ( do_inserts ) && ( (idx - lag) >= 0 ) && ( (idx - lag) >= lower_bound ) && ( (idx - lag) <= local_max_index ) && ( (idx - lag) <= upper_bound ) && ( ((idx - lag) % 2) == 1 ) && ( ! entry_in_cache2(cache_ptr, type, (idx - lag)) ) ) { if ( verbose ) HDfprintf(stdout, "(i, %d, %d) ", type, (idx - lag)); insert_entry2(file_ptr, type, (idx - lag), dirty_inserts, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx - lag + 1) >= 0 ) && ( (idx - lag + 1) >= lower_bound ) && ( (idx - lag + 1) <= local_max_index ) && ( (idx - lag + 1) <= upper_bound ) && ( ( (idx - lag + 1) % 3 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(p, %d, %d) ", type, (idx - lag + 1)); protect_entry2(file_ptr, type, (idx - lag + 1)); } if ( ( pass2 ) && ( (idx - lag + 2) >= 0 ) && ( (idx - lag + 2) >= lower_bound ) && ( (idx - lag + 2) <= local_max_index ) && ( (idx - lag + 2) <= upper_bound ) && ( ( (idx - lag + 2) % 3 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag + 2)); unprotect_entry2(file_ptr, type, idx-lag+2, NO_CHANGE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( do_renames ) && ( (idx - lag + 2) >= 0 ) && ( (idx - lag + 2) >= lower_bound ) && ( (idx - lag + 2) <= local_max_index ) && ( (idx - lag + 2) <= upper_bound ) && ( ( (idx - lag + 2) % 3 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(r, %d, %d, %d) ", type, (idx - lag + 2), (int)rename_to_main_addr); rename_entry2(cache_ptr, type, (idx - lag + 2), rename_to_main_addr); } if ( ( pass2 ) && ( (idx - lag + 3) >= 0 ) && ( (idx - lag + 3) >= lower_bound ) && ( (idx - lag + 3) <= local_max_index ) && ( (idx - lag + 3) <= upper_bound ) && ( ( (idx - lag + 3) % 5 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(p, %d, %d) ", type, (idx - lag + 3)); protect_entry2(file_ptr, type, (idx - lag + 3)); } if ( ( pass2 ) && ( (idx - lag + 5) >= 0 ) && ( (idx - lag + 5) >= lower_bound ) && ( (idx - lag + 5) <= local_max_index ) && ( (idx - lag + 5) <= upper_bound ) && ( ( (idx - lag + 5) % 5 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag + 5)); unprotect_entry2(file_ptr, type, idx-lag+5, NO_CHANGE, H5C2__NO_FLAGS_SET); } if ( do_mult_ro_protects ) { if ( ( pass2 ) && ( (idx - lag + 5) >= 0 ) && ( (idx - lag + 5) >= lower_bound ) && ( (idx - lag + 5) < local_max_index ) && ( (idx - lag + 5) < upper_bound ) && ( (idx - lag + 5) % 9 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(p-ro, %d, %d) ", type, (idx - lag + 5)); protect_entry_ro2(file_ptr, type, (idx - lag + 5)); } if ( ( pass2 ) && ( (idx - lag + 6) >= 0 ) && ( (idx - lag + 6) >= lower_bound ) && ( (idx - lag + 6) < local_max_index ) && ( (idx - lag + 6) < upper_bound ) && ( (idx - lag + 6) % 11 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(p-ro, %d, %d) ", type, (idx - lag + 6)); protect_entry_ro2(file_ptr, type, (idx - lag + 6)); } if ( ( pass2 ) && ( (idx - lag + 7) >= 0 ) && ( (idx - lag + 7) >= lower_bound ) && ( (idx - lag + 7) < local_max_index ) && ( (idx - lag + 7) < upper_bound ) && ( (idx - lag + 7) % 13 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(p-ro, %d, %d) ", type, (idx - lag + 7)); protect_entry_ro2(file_ptr, type, (idx - lag + 7)); } if ( ( pass2 ) && ( (idx - lag + 7) >= 0 ) && ( (idx - lag + 7) >= lower_bound ) && ( (idx - lag + 7) < local_max_index ) && ( (idx - lag + 7) < upper_bound ) && ( (idx - lag + 7) % 9 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(u-ro, %d, %d) ", type, (idx - lag + 7)); unprotect_entry2(file_ptr, type, (idx - lag + 7), FALSE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx - lag + 8) >= 0 ) && ( (idx - lag + 8) >= lower_bound ) && ( (idx - lag + 8) < local_max_index ) && ( (idx - lag + 8) < upper_bound ) && ( (idx - lag + 8) % 11 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(u-ro, %d, %d) ", type, (idx - lag + 8)); unprotect_entry2(file_ptr, type, (idx - lag + 8), FALSE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx - lag + 9) >= 0 ) && ( (idx - lag + 9) >= lower_bound ) && ( (idx - lag + 9) < local_max_index ) && ( (idx - lag + 9) < upper_bound ) && ( (idx - lag + 9) % 13 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(u-ro, %d, %d) ", type, (idx - lag + 9)); unprotect_entry2(file_ptr, type, (idx - lag + 9), FALSE, H5C2__NO_FLAGS_SET); } } /* if ( do_mult_ro_protects ) */ if ( ( pass2 ) && ( idx >= 0 ) && ( idx >= lower_bound ) && ( idx <= local_max_index ) && ( idx <= upper_bound ) ) { if ( verbose ) HDfprintf(stdout, "(p, %d, %d) ", type, idx); protect_entry2(file_ptr, type, idx); } if ( ( pass2 ) && ( (idx + lag - 2) >= 0 ) && ( (idx + lag - 2) >= lower_bound ) && ( (idx + lag - 2) <= local_max_index ) && ( (idx + lag - 2) <= upper_bound ) && ( ( (idx + lag - 2) % 7 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag - 2)); unprotect_entry2(file_ptr, type, idx+lag-2, NO_CHANGE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx + lag - 1) >= 0 ) && ( (idx + lag - 1) >= lower_bound ) && ( (idx + lag - 1) <= local_max_index ) && ( (idx + lag - 1) <= upper_bound ) && ( ( (idx + lag - 1) % 7 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "(p, %d, %d) ", type, (idx + lag - 1)); protect_entry2(file_ptr, type, (idx + lag - 1)); } if ( do_destroys ) { if ( ( pass2 ) && ( (idx + lag) >= 0 ) && ( (idx + lag) >= lower_bound ) && ( ( idx + lag) <= local_max_index ) && ( ( idx + lag) <= upper_bound ) ) { switch ( (idx + lag) %4 ) { case 0: if ( (entries2[type])[idx+lag].is_dirty ) { unprotect_entry2(file_ptr, type, idx + lag, NO_CHANGE, H5C2__NO_FLAGS_SET); } else { unprotect_entry2(file_ptr, type, idx + lag, dirty_unprotects, H5C2__NO_FLAGS_SET); } break; case 1: /* we just did an insert */ unprotect_entry2(file_ptr, type, idx + lag, NO_CHANGE, H5C2__NO_FLAGS_SET); break; case 2: if ( (entries2[type])[idx + lag].is_dirty ) { unprotect_entry2(file_ptr, type, idx + lag, NO_CHANGE, H5C2__DELETED_FLAG); } else { unprotect_entry2(file_ptr, type, idx + lag, dirty_destroys, H5C2__DELETED_FLAG); } break; case 3: /* we just did an insrt */ unprotect_entry2(file_ptr, type, idx + lag, NO_CHANGE, H5C2__DELETED_FLAG); break; default: HDassert(0); /* this can't happen... */ break; } } } else { if ( ( pass2 ) && ( (idx + lag) >= 0 ) && ( (idx + lag) >= lower_bound ) && ( ( idx + lag) <= local_max_index ) && ( ( idx + lag) <= upper_bound ) ) { if ( verbose ) HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag)); unprotect_entry2(file_ptr, type, idx + lag, dirty_unprotects, H5C2__NO_FLAGS_SET); } } idx--; if ( verbose ) HDfprintf(stdout, "\n"); } /* while ( ( pass2 ) && ( idx >= lower_bound - lag ) ) */ end_trans(file_ptr, cache_ptr, verbose, trans_num, "jrnl_row_major_scan_backward inner loop"); if ( verbose ) HDfprintf(stdout, "end trans %lld.\n", (long long)trans_num); upper_bound = lower_bound - (2 * lag) - 2; lower_bound = upper_bound - 8; idx = upper_bound + lag; } /* while ( ( pass2 ) && ( idx >= -lag ) ) */ type--; } /* while ( ( pass2 ) && ( type >= 0 ) ) */ if ( ( pass2 ) && ( display_stats ) ) { H5C2_stats(cache_ptr, "test cache", display_detailed_stats); } return; } /* jrnl_row_major_scan_backward2() */ /*------------------------------------------------------------------------- * Function: jrnl_row_major_scan_forward2() * * Purpose: Do a sequence of inserts, protects, unprotects, renames, * and destroys broken into transactions while scanning * through the set of entries. * * If pass2 is false on entry, do nothing. * * Note that this function is an adaption of * row_major_scan_forward2(). * * Return: void * * Programmer: John Mainzer * 5/20/08 * * Modifications: * * None. * *------------------------------------------------------------------------- */ void jrnl_row_major_scan_forward2(H5F_t * file_ptr, int32_t max_index, int32_t lag, hbool_t verbose, hbool_t reset_stats, hbool_t display_stats, hbool_t display_detailed_stats, hbool_t do_inserts, hbool_t dirty_inserts, hbool_t do_renames, hbool_t rename_to_main_addr, hbool_t do_destroys, hbool_t do_mult_ro_protects, int dirty_destroys, int dirty_unprotects, uint64_t trans_num) { const char * fcn_name = "jrnl_row_major_scan_forward2"; H5C2_t * cache_ptr; int32_t type; int32_t idx; int32_t local_max_index; int32_t lower_bound; int32_t upper_bound; if ( verbose ) HDfprintf(stdout, "%s(): entering.\n", fcn_name); if ( pass2 ) { cache_ptr = file_ptr->shared->cache2; HDassert( cache_ptr != NULL ); HDassert( lag >= 10 ); type = 0; if ( reset_stats ) { H5C2_stats__reset(cache_ptr); } } while ( ( pass2 ) && ( type < NUMBER_OF_ENTRY_TYPES ) ) { idx = -lag; local_max_index = MIN(max_index, max_indices2[type]); lower_bound = 0; upper_bound = lower_bound + 8; while ( ( pass2 ) && ( idx <= (local_max_index + lag) ) ) { if ( idx == ( lower_bound - lag ) ) { trans_num++; begin_trans(cache_ptr, verbose, trans_num, "jrnl_row_major_scan_forward inner loop"); if ( verbose ) HDfprintf(stdout, "begin trans %lld.\n", (long long)trans_num); if ( verbose ) HDfprintf(stdout, "(%d, %d)\n", lower_bound, upper_bound); } while ( ( pass2 ) && ( idx <= upper_bound + lag ) ) { if ( verbose ) { HDfprintf(stdout, "%lld:%d:%d: ", trans_num, type, idx); } if ( ( pass2 ) && ( do_inserts ) && ( (idx + lag) >= 0 ) && ( (idx + lag) >= lower_bound ) && ( (idx + lag) <= local_max_index ) && ( (idx + lag) <= upper_bound ) && ( ((idx + lag) % 2) == 0 ) && ( ! entry_in_cache2(cache_ptr, type, (idx + lag)) ) ) { if ( verbose ) HDfprintf(stdout, "1(i, %d, %d) ", type, (idx + lag)); /*** insert entry idx + lag (if not already present *** */ insert_entry2(file_ptr, type, (idx + lag), dirty_inserts, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx + lag - 1) >= 0 ) && ( (idx + lag - 1) >= lower_bound ) && ( (idx + lag - 1) <= local_max_index ) && ( (idx + lag - 1) <= upper_bound ) && ( ( (idx + lag - 1) % 3 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "2(p, %d, %d) ", type, (idx + lag - 1)); /*** protect entry idx + lag - 1 ***/ protect_entry2(file_ptr, type, (idx + lag - 1)); } if ( ( pass2 ) && ( (idx + lag - 2) >= 0 ) && ( (idx + lag - 2) >= lower_bound ) && ( (idx + lag - 2) <= local_max_index ) && ( (idx + lag - 2) <= upper_bound ) && ( ( (idx + lag - 2) % 3 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "3(u, %d, %d) ", type, (idx + lag - 2)); /*** unprotect entry idx + lag - 2 ***/ unprotect_entry2(file_ptr, type, idx+lag-2, NO_CHANGE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( do_renames ) && ( (idx + lag - 2) >= 0 ) && ( (idx + lag - 2) >= lower_bound ) && ( (idx + lag - 2) <= local_max_index ) && ( (idx + lag - 2) <= upper_bound ) && ( ( (idx + lag - 2) % 3 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "4(r, %d, %d, %d) ", type, (idx + lag - 2), (int)rename_to_main_addr); /*** rename entry idx + lag -2 ***/ rename_entry2(cache_ptr, type, (idx + lag - 2), rename_to_main_addr); } if ( ( pass2 ) && ( (idx + lag - 3) >= 0 ) && ( (idx + lag - 3) >= lower_bound ) && ( (idx + lag - 3) <= local_max_index ) && ( (idx + lag - 3) <= upper_bound ) && ( ( (idx + lag - 3) % 5 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "5(p, %d, %d) ", type, (idx + lag - 3)); /*** protect entry idx + lag - 3 ***/ protect_entry2(file_ptr, type, (idx + lag - 3)); } if ( ( pass2 ) && ( (idx + lag - 5) >= 0 ) && ( (idx + lag - 5) >= lower_bound ) && ( (idx + lag - 5) <= local_max_index ) && ( (idx + lag - 5) <= upper_bound ) && ( ( (idx + lag - 5) % 5 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "6(u, %d, %d) ", type, (idx + lag - 5)); /*** unprotect entry idx + lag - 5 ***/ unprotect_entry2(file_ptr, type, idx+lag-5, NO_CHANGE, H5C2__NO_FLAGS_SET); } if ( do_mult_ro_protects ) { if ( ( pass2 ) && ( (idx + lag - 5) >= 0 ) && ( (idx + lag - 5) >= lower_bound ) && ( (idx + lag - 5) < local_max_index ) && ( (idx + lag - 5) < upper_bound ) && ( (idx + lag - 5) % 9 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "7(p-ro, %d, %d) ", type, (idx + lag - 5)); /*** protect ro entry idx + lag - 5 ***/ protect_entry_ro2(file_ptr, type, (idx + lag - 5)); } if ( ( pass2 ) && ( (idx + lag - 6) >= 0 ) && ( (idx + lag - 6) >= lower_bound ) && ( (idx + lag - 6) < local_max_index ) && ( (idx + lag - 6) < upper_bound ) && ( (idx + lag - 6) % 11 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "8(p-ro, %d, %d) ", type, (idx + lag - 6)); /*** protect ro entry idx + lag - 6 ***/ protect_entry_ro2(file_ptr, type, (idx + lag - 6)); } if ( ( pass2 ) && ( (idx + lag - 7) >= 0 ) && ( (idx + lag - 7) >= lower_bound ) && ( (idx + lag - 7) < local_max_index ) && ( (idx + lag - 7) < upper_bound ) && ( (idx + lag - 7) % 13 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "9(p-ro, %d, %d) ", type, (idx + lag - 7)); /*** protect ro entry idx + lag - 7 ***/ protect_entry_ro2(file_ptr, type, (idx + lag - 7)); } if ( ( pass2 ) && ( (idx + lag - 7) >= 0 ) && ( (idx + lag - 7) >= lower_bound ) && ( (idx + lag - 7) < local_max_index ) && ( (idx + lag - 7) < upper_bound ) && ( (idx + lag - 7) % 9 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "10(u-ro, %d, %d) ", type, (idx + lag - 7)); /*** unprotect ro entry idx + lag - 7 ***/ unprotect_entry2(file_ptr, type, (idx + lag - 7), FALSE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx + lag - 8) >= 0 ) && ( (idx + lag - 8) >= lower_bound ) && ( (idx + lag - 8) < local_max_index ) && ( (idx + lag - 8) < upper_bound ) && ( (idx + lag - 8) % 11 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "11(u-ro, %d, %d) ", type, (idx + lag - 8)); /*** unprotect ro entry idx + lag - 8 ***/ unprotect_entry2(file_ptr, type, (idx + lag - 8), FALSE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx + lag - 9) >= 0 ) && ( (idx + lag - 9) >= lower_bound ) && ( (idx + lag - 9) < local_max_index ) && ( (idx + lag - 9) < upper_bound ) && ( (idx + lag - 9) % 13 == 0 ) ) { if ( verbose ) HDfprintf(stdout, "12(u-ro, %d, %d) ", type, (idx + lag - 9)); /*** unprotect ro entry idx + lag - 9 ***/ unprotect_entry2(file_ptr, type, (idx + lag - 9), FALSE, H5C2__NO_FLAGS_SET); } } /* if ( do_mult_ro_protects ) */ if ( ( pass2 ) && ( idx >= 0 ) && ( idx >= lower_bound ) && ( idx <= local_max_index ) && ( idx <= upper_bound ) ) { if ( verbose ) HDfprintf(stdout, "13(p, %d, %d) ", type, idx); /*** protect entry idx ***/ protect_entry2(file_ptr, type, idx); } if ( ( pass2 ) && ( (idx - lag + 2) >= 0 ) && ( (idx - lag + 2) >= lower_bound ) && ( (idx - lag + 2) <= local_max_index ) && ( (idx - lag + 2) <= upper_bound ) && ( ( (idx - lag + 2) % 7 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "14(u, %d, %d) ", type, (idx - lag + 2)); /*** unprotect entry idx - lag + 2 ***/ unprotect_entry2(file_ptr, type, idx-lag+2, NO_CHANGE, H5C2__NO_FLAGS_SET); } if ( ( pass2 ) && ( (idx - lag + 1) >= 0 ) && ( (idx - lag + 1) >= lower_bound ) && ( (idx - lag + 1) <= local_max_index ) && ( (idx - lag + 1) <= upper_bound ) && ( ( (idx - lag + 1) % 7 ) == 0 ) ) { if ( verbose ) HDfprintf(stdout, "15(p, %d, %d) ", type, (idx - lag + 1)); /*** protect entry idx - lag + 1 ***/ protect_entry2(file_ptr, type, (idx - lag + 1)); } if ( do_destroys ) { if ( ( pass2 ) && ( (idx - lag) >= 0 ) && ( (idx - lag) >= lower_bound ) && ( ( idx - lag) <= local_max_index ) && ( ( idx - lag) <= upper_bound ) ) { switch ( (idx - lag) %4 ) { case 0: /* we just did an insert */ if ( verbose ) HDfprintf(stdout, "16(u, %d, %d) ", type, (idx - lag)); /*** unprotect entry NC idx - lag ***/ unprotect_entry2(file_ptr, type, idx - lag, NO_CHANGE, H5C2__NO_FLAGS_SET); break; case 1: if ( (entries2[type])[idx-lag].is_dirty ) { if ( verbose ) HDfprintf(stdout, "17(u, %d, %d) ", type, (idx - lag)); /*** unprotect entry NC idx - lag ***/ unprotect_entry2(file_ptr, type, idx - lag, NO_CHANGE, H5C2__NO_FLAGS_SET); } else { if ( verbose ) HDfprintf(stdout, "18(u, %d, %d) ", type, (idx - lag)); /*** unprotect entry idx - lag ***/ unprotect_entry2(file_ptr, type, idx - lag, dirty_unprotects, H5C2__NO_FLAGS_SET); } break; case 2: /* we just did an insrt */ if ( verbose ) HDfprintf(stdout, "19(u-del, %d, %d) ", type, (idx - lag)); /*** unprotect delete idx - lag ***/ unprotect_entry2(file_ptr, type, idx - lag, NO_CHANGE, H5C2__DELETED_FLAG); break; case 3: if ( (entries2[type])[idx-lag].is_dirty ) { if ( verbose ) HDfprintf(stdout, "20(u-del, %d, %d) ", type, (idx - lag)); /*** unprotect delete idx - lag ***/ unprotect_entry2(file_ptr, type, idx - lag, NO_CHANGE, H5C2__DELETED_FLAG); } else { if ( verbose ) HDfprintf(stdout, "21(u-del, %d, %d) ", type, (idx - lag)); /*** unprotect delete idx - lag ***/ unprotect_entry2(file_ptr, type, idx - lag, dirty_destroys, H5C2__DELETED_FLAG); } break; default: HDassert(0); /* this can't happen... */ break; } } } else { if ( ( pass2 ) && ( (idx - lag) >= 0 ) && ( (idx - lag) >= lower_bound ) && ( ( idx - lag) <= local_max_index ) && ( ( idx - lag) <= upper_bound ) ) { if ( verbose ) HDfprintf(stdout, "22(u, %d, %d) ", type, (idx - lag)); /*** unprotect idx - lag ***/ unprotect_entry2(file_ptr, type, idx - lag, dirty_unprotects, H5C2__NO_FLAGS_SET); } } idx++; if ( verbose ) HDfprintf(stdout, "\n"); } /* while ( ( pass2 ) && ( idx <= upper_bound ) ) */ end_trans(file_ptr, cache_ptr, verbose, trans_num, "jrnl_row_major_scan_forward inner loop"); if ( verbose ) HDfprintf(stdout, "end trans %lld.\n", (long long)trans_num); lower_bound = upper_bound + (2 * lag) + 2; upper_bound = lower_bound + 8; idx = lower_bound - lag; } /* while ( ( pass2 ) && ( idx <= (local_max_index + lag) ) ) */ type++; } /* while ( ( pass2 ) && ( type < NUMBER_OF_ENTRY_TYPES ) ) */ if ( ( pass2 ) && ( display_stats ) ) { H5C2_stats(cache_ptr, "test cache", display_detailed_stats); } return; } /* jrnl_row_major_scan_forward2() */ /*------------------------------------------------------------------------- * Function: open_existing_file_for_journaling() * * Purpose: If pass2 is true on entry, open the specified a HDF5 file * with journaling enabled and journal file with the specified * name. Return pointers to the cache data structure and file * data structures, and verify that it contains the expected data. * * On failure, set pass2 to FALSE, and set failure_mssg2 * to point to an appropriate failure message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5/13/08 * * Modifications: * *------------------------------------------------------------------------- */ static void open_existing_file_for_journaling(const char * hdf_file_name, const char * journal_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr) { const char * fcn_name = "open_existing_file_for_journaling()"; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; int cp = 0; herr_t result; H5AC2_jnl_config_t jnl_config; hid_t fapl_id = -1; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; if ( pass2 ) { if ( ( hdf_file_name == NULL ) || ( journal_file_name == NULL ) || ( file_id_ptr == NULL ) || ( file_ptr_ptr == NULL ) || ( cache_ptr_ptr == NULL ) ) { failure_mssg2 = "Bad param(s) on entry to open_existing_file_for_journaling().\n"; pass2 = FALSE; } else if ( strlen(journal_file_name) > H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { failure_mssg2 = "journal file name too long.\n"; pass2 = FALSE; } else if ( verbose ) { HDfprintf(stdout, "%s: HDF file name = \"%s\".\n", fcn_name, hdf_file_name); HDfprintf(stdout, "%s: journal file name = \"%s\".\n", fcn_name, journal_file_name); } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* create a file access propertly list. */ if ( pass2 ) { fapl_id = H5Pcreate(H5P_FILE_ACCESS); if ( fapl_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pcreate() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* call H5Pset_libver_bounds() on the fapl_id */ if ( pass2 ) { if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_libver_bounds() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Pget_jnl_config(fapl_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = TRUE; strcpy(jnl_config.journal_file_path, journal_file_name); jnl_config.journal_recovered = FALSE; jnl_config.jbrb_buf_size = (8 * 1024); jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = FALSE; jnl_config.jbrb_human_readable = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { result = H5Pset_jnl_config(fapl_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_jnl_config() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /**************************************/ /* open the file with the fapl above. */ /**************************************/ /* open the file using fapl_id */ if ( pass2 ) { file_id = H5Fopen(hdf_file_name, H5F_ACC_RDWR, fapl_id); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (1).\n"; } else { file_ptr = H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr."; if ( verbose ) { HDfprintf(stdout, "%s: Can't get file_ptr.\n", fcn_name); } } } } /* At least within the context of the cache2 test code, there should be * no need to allocate space for test entries since we are re-opening * the file, and any needed space allocation should have been done at * file creation. */ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * to the cache structure */ if ( pass2 ) { if ( file_ptr->shared->cache2 == NULL ) { pass2 = FALSE; failure_mssg2 = "can't get cache2 pointer(1).\n"; } else { cache_ptr = file_ptr->shared->cache2; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { *file_id_ptr = file_id; *file_ptr_ptr = file_ptr; *cache_ptr_ptr = cache_ptr; } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d -- exiting.\n", fcn_name, cp++); return; } /* open_existing_file_for_journaling() */ /*------------------------------------------------------------------------- * Function: open_existing_file_without_journaling() * * Purpose: If pass2 is true on entry, open the specified a HDF5 file * with journaling disabled. Return pointers to the cache * data structure and file data structures, and verify that * it contains the expected data. * * On failure, set pass2 to FALSE, and set failure_mssg2 * to point to an appropriate failure message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 7/10/08 * * Modifications: * *------------------------------------------------------------------------- */ static void open_existing_file_without_journaling(const char * hdf_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr) { const char * fcn_name = "open_existing_file_without_journaling()"; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; int cp = 0; hid_t fapl_id = -1; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; if ( pass2 ) { if ( ( hdf_file_name == NULL ) || ( file_id_ptr == NULL ) || ( file_ptr_ptr == NULL ) || ( cache_ptr_ptr == NULL ) ) { failure_mssg2 = "Bad param(s) on entry to open_existing_file_without_journaling().\n"; pass2 = FALSE; } else { if ( verbose ) { HDfprintf(stdout, "%s: HDF file name = \"%s\".\n", fcn_name, hdf_file_name); } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* create a file access propertly list. */ if ( pass2 ) { fapl_id = H5Pcreate(H5P_FILE_ACCESS); if ( fapl_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pcreate() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* call H5Pset_libver_bounds() on the fapl_id */ if ( pass2 ) { if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_libver_bounds() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /**************************************/ /* open the file with the fapl above. */ /**************************************/ /* open the file using fapl_id */ if ( pass2 ) { file_id = H5Fopen(hdf_file_name, H5F_ACC_RDWR, fapl_id); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (2).\n"; } else { file_ptr = H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr."; if ( verbose ) { HDfprintf(stdout, "%s: Can't get file_ptr.\n", fcn_name); } } } } /* At least within the context of the cache2 test code, there should be * no need to allocate space for test entries since we are re-opening * the file, and any needed space allocation should have been done at * file creation. */ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * to the cache structure */ if ( pass2 ) { if ( file_ptr->shared->cache2 == NULL ) { pass2 = FALSE; failure_mssg2 = "can't get cache2 pointer(1).\n"; } else { cache_ptr = file_ptr->shared->cache2; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { *file_id_ptr = file_id; *file_ptr_ptr = file_ptr; *cache_ptr_ptr = cache_ptr; } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d -- exiting.\n", fcn_name, cp++); return; } /* open_existing_file_without_journaling() */ /*------------------------------------------------------------------------- * Function: setup_cache_for_journaling() * * Purpose: If pass2 is true on entry, create a HDF5 file with * journaling enabled and journal file with the specified name. * Return pointers to the cache data structure and file data * structures. and verify that it contains the expected data. * * On failure, set pass2 to FALSE, and set failure_mssg2 * to point to an appropriate failure message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5/13/08 * * Modifications: * *------------------------------------------------------------------------- */ static void setup_cache_for_journaling(const char * hdf_file_name, const char * journal_file_name, hid_t * file_id_ptr, H5F_t ** file_ptr_ptr, H5C2_t ** cache_ptr_ptr, #if USE_CORE_DRIVER hbool_t use_core_driver_if_avail) #else /* USE_CORE_DRIVER */ hbool_t UNUSED use_core_driver_if_avail) #endif /* USE_CORE_DRIVER */ { const char * fcn_name = "setup_cache_for_journaling()"; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; int cp = 0; herr_t result; H5AC2_cache_config_t mdj_config = { /* int version = */ H5C2__CURR_AUTO_SIZE_CTL_VER, /* hbool_t rpt_fcn_enabled = */ FALSE, /* hbool_t open_trace_file = */ FALSE, /* hbool_t close_trace_file = */ FALSE, /* char trace_file_name[] = */ "", /* hbool_t evictions_enabled = */ TRUE, /* hbool_t set_initial_size = */ TRUE, /* size_t initial_size = */ ( 64 * 1024 ), /* double min_clean_fraction = */ 0.5, /* size_t max_size = */ (16 * 1024 * 1024 ), /* size_t min_size = */ ( 8 * 1024 ), /* long int epoch_length = */ 50000, /* enum H5C2_cache_incr_mode incr_mode = */ H5C2_incr__off, /* double lower_hr_threshold = */ 0.9, /* double increment = */ 2.0, /* hbool_t apply_max_increment = */ TRUE, /* size_t max_increment = */ (4 * 1024 * 1024), /* enum H5C2_cache_flash_incr_mode */ /* flash_incr_mode = */ H5C2_flash_incr__off, /* double flash_multiple = */ 1.0, /* double flash_threshold = */ 0.25, /* enum H5C2_cache_decr_mode decr_mode = */ H5C2_decr__off, /* double upper_hr_threshold = */ 0.999, /* double decrement = */ 0.9, /* hbool_t apply_max_decrement = */ TRUE, /* size_t max_decrement = */ (1 * 1024 * 1024), /* int epochs_before_eviction = */ 3, /* hbool_t apply_empty_reserve = */ TRUE, /* double empty_reserve = */ 0.1, /* int dirty_bytes_threshold = */ (8 * 1024) }; H5AC2_jnl_config_t jnl_config = { /* int version = */ H5AC2__CURR_JNL_CONFIG_VER, /* hbool_t enable_journaling = */ TRUE, /* char journal_file_path[] = */ "", /* hbool_t journal_recovered = */ FALSE, /* size_t jbrb_buf_size = */ (8 * 1024), /* int jbrb_num_bufs = */ 2, /* hbool_t jbrb_use_aio = */ FALSE, /* hbool_t jbrb_human_readable = */ TRUE }; hid_t fapl_id = -1; hid_t file_id = -1; haddr_t actual_base_addr; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; if ( pass2 ) { if ( ( hdf_file_name == NULL ) || ( journal_file_name == NULL ) || ( file_id_ptr == NULL ) || ( file_ptr_ptr == NULL ) || ( cache_ptr_ptr == NULL ) ) { failure_mssg2 = "Bad param(s) on entry to setup_cache_for_journaling().\n"; pass2 = FALSE; } else if ( strlen(journal_file_name) > H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { failure_mssg2 = "journal file name too long.\n"; pass2 = FALSE; } else { strcpy(jnl_config.journal_file_path, journal_file_name); if ( verbose ) { HDfprintf(stdout, "%s: HDF file name = \"%s\".\n", fcn_name, hdf_file_name); HDfprintf(stdout, "%s: journal file name = \"%s\".\n", fcn_name, journal_file_name); } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* create a file access propertly list. */ if ( pass2 ) { fapl_id = H5Pcreate(H5P_FILE_ACCESS); if ( fapl_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pcreate() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* call H5Pset_libver_bounds() on the fapl_id */ if ( pass2 ) { if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_libver_bounds() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { result = H5Pset_mdc_config(fapl_id, (H5AC_cache_config_t *)&mdj_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_mdc_config() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { result = H5Pset_jnl_config(fapl_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_mdc_config() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); #if USE_CORE_DRIVER if ( ( pass2 ) && ( use_core_driver_if_avail ) ) { if ( H5Pset_fapl_core(fapl_id, 64 * 1024 * 1024, FALSE) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5P_set_fapl_core() failed.\n"; } } #endif /* USE_CORE_DRIVER */ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /**************************************/ /* Create a file with the fapl above. */ /**************************************/ /* create the file using fapl_id */ if ( pass2 ) { file_id = H5Fcreate(hdf_file_name, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fcreate() failed.\n"; } else { file_ptr = H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr."; if ( verbose ) { HDfprintf(stdout, "%s: Can't get file_ptr.\n", fcn_name); } } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { /* allocate space for test entries */ actual_base_addr = H5MF_alloc(file_ptr, H5FD_MEM_DEFAULT, H5P_DEFAULT, (hsize_t)(ADDR_SPACE_SIZE + BASE_ADDR)); if ( actual_base_addr == HADDR_UNDEF ) { pass2 = FALSE; failure_mssg2 = "H5MF_alloc() failed."; if ( verbose ) { HDfprintf(stdout, "%s: H5MF_alloc() failed.\n", fcn_name); } } else if ( actual_base_addr > BASE_ADDR ) { /* If this happens, must increase BASE_ADDR so that the * actual_base_addr is <= BASE_ADDR. This should only happen * if the size of the superblock is increase. */ pass2 = FALSE; failure_mssg2 = "actual_base_addr > BASE_ADDR"; if ( verbose ) { HDfprintf(stdout, "%s: actual_base_addr > BASE_ADDR.\n", fcn_name); } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * to the cache structure */ if ( pass2 ) { if ( file_ptr->shared->cache2 == NULL ) { pass2 = FALSE; failure_mssg2 = "can't get cache2 pointer(1).\n"; } else { cache_ptr = file_ptr->shared->cache2; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); reset_entries2(); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* close the fapl */ if ( pass2 ) { if ( H5Pclose(fapl_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "error closing fapl.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { *file_id_ptr = file_id; *file_ptr_ptr = file_ptr; *cache_ptr_ptr = cache_ptr; } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d -- exiting.\n", fcn_name, cp++); return; } /* setup_cache_for_journaling() */ /*------------------------------------------------------------------------- * Function: takedown_cache_after_journaling() * * Purpose: If file_id >= 0, close the associated file, and then delete * it. Verify that they journal file has been deleted. * * Return: void * * Programmer: John Mainzer * 5/13/08 * * Modifications: * *------------------------------------------------------------------------- */ static void takedown_cache_after_journaling(hid_t file_id, const char * filename, const char * journal_filename, hbool_t use_core_driver_if_avail) { hbool_t verbose = FALSE; int error; if ( file_id >= 0 ) { if ( H5Fclose(file_id) < 0 ) { if ( pass2 ) { pass2 = FALSE; failure_mssg2 = "file close failed."; } } else if ( ( ( ! USE_CORE_DRIVER ) || ( ! use_core_driver_if_avail ) ) && ( ( error = HDremove(filename) ) != 0 ) ) { if ( verbose ) { HDfprintf(stdout, "HDremove(\"%s\") failed, returned %d, errno = %d = %s.\n", filename, error, errno, strerror(errno)); } if ( pass2 ) { pass2 = FALSE; failure_mssg2 = "HDremove() failed (1).\n"; } } } verify_journal_deleted(journal_filename); return; } /* takedown_cache_after_journaling() */ /*------------------------------------------------------------------------- * Function: verify_journal_contents() * * Purpose: If pass2 is true on entry, verify that the contents of the * journal file matches that of the expected file. If * differences are detected, or if any other error is detected, * set pass2 to FALSE and set failure_mssg2 to point to an * appropriate error message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5/06/08 * * Modifications: * *------------------------------------------------------------------------- */ static void verify_journal_contents(const char * journal_file_path_ptr, const char * expected_file_path_ptr) { const char * fcn_name = "verify_journal_contents()"; char ch; char journal_buf[(8 * 1024) + 1]; char expected_buf[(8 * 1024) + 1]; hbool_t verbose = FALSE; size_t cur_buf_len; const size_t max_buf_len = (8 * 1024); size_t journal_len = 0; size_t expected_len = 0; size_t first_line_len; size_t journal_remainder_len = 0; size_t expected_remainder_len = 0; ssize_t read_result; int journal_file_fd = -1; int expected_file_fd = -1; h5_stat_t buf; if ( pass2 ) { if ( journal_file_path_ptr == NULL ) { failure_mssg2 = "journal_file_path_ptr NULL on entry?!?", pass2 = FALSE; } else if ( expected_file_path_ptr == NULL ) { failure_mssg2 = "expected_file_path_ptr NULL on entry?!?", pass2 = FALSE; } } /* get the actual length of the journal file */ if ( pass2 ) { if ( HDstat(journal_file_path_ptr, &buf) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat(j) failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "stat() failed on journal file."; pass2 = FALSE; } else { if ( (buf.st_size) == 0 ) { failure_mssg2 = "Journal file empty?!?"; pass2 = FALSE; } else { journal_len = (size_t)(buf.st_size); if ( verbose ) { HDfprintf(stdout, "%s: journal_len = %d.\n", fcn_name, (int)journal_len); } } } } /* get the actual length of the expected file */ if ( pass2 ) { if ( HDstat(expected_file_path_ptr, &buf) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat(e) failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "stat() failed on expected file."; pass2 = FALSE; } else { if ( (buf.st_size) == 0 ) { failure_mssg2 = "Expected file empty?!?"; pass2 = FALSE; } else { expected_len = (size_t)(buf.st_size); if ( verbose ) { HDfprintf(stdout, "%s: expected_len = %d.\n", fcn_name, (int)expected_len); } } } } /* open the journal file */ if ( pass2 ) { if ( (journal_file_fd = HDopen(journal_file_path_ptr, O_RDONLY, 0777)) == -1 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDopen(j) failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "Can't open journal file."; pass2 = FALSE; } } /* open the expected file */ if ( pass2 ) { if ( (expected_file_fd = HDopen(expected_file_path_ptr, O_RDONLY, 0777)) == -1 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDopen(e) failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "Can't open expected file."; pass2 = FALSE; } } /* The first lines of the journal and expected files will usually differ * in creation date. We could look at everything else on the line, but * for now we will just skip past it, and compute the length of the remainder * of the journal and expected files as we do so. * * Do this by reading the file one character at a time until we hit a newline. * This is very inefficient, but this is test code, and the first line * can't be very long. */ if ( pass2 ) { first_line_len = 1; read_result = HDread(journal_file_fd, &ch, 1); while ( ( ch != '\n' ) && ( first_line_len < 128 ) && ( read_result == 1 ) ) { first_line_len++; read_result = HDread(journal_file_fd, &ch, 1); } if ( ch != '\n' ) { failure_mssg2 = "error skipping first line of journal file."; pass2 = FALSE; } else if ( first_line_len > journal_len ) { failure_mssg2 = "first_line_len > journal_len?!?"; pass2 = FALSE; } else { journal_remainder_len = journal_len - first_line_len; } } if ( pass2 ) { first_line_len = 1; read_result = HDread(expected_file_fd, &ch, 1); while ( ( ch != '\n' ) && ( first_line_len < 128 ) && ( read_result == 1 ) ) { first_line_len++; read_result = HDread(expected_file_fd, &ch, 1); } if ( ch != '\n' ) { failure_mssg2 = "error skipping first line of expected file."; pass2 = FALSE; } else if ( first_line_len > expected_len ) { failure_mssg2 = "first_line_len > expected_len?!?"; pass2 = FALSE; } else { expected_remainder_len = expected_len - first_line_len; } } if ( pass2 ) { if ( journal_remainder_len != expected_remainder_len ) { failure_mssg2 = "Unexpected journal file contents(1)."; pass2 = FALSE; } } /* If we get this far without an error, the lengths of the actual * and expected files (after skipping the first line) are identical. * Thus we have to go and compare the actual data. */ while ( ( pass2 ) && ( journal_remainder_len > 0 ) ) { HDassert( journal_remainder_len == expected_remainder_len ); if ( journal_remainder_len > max_buf_len ) { cur_buf_len = max_buf_len; journal_remainder_len -= max_buf_len; expected_remainder_len -= max_buf_len; } else { cur_buf_len = journal_remainder_len; journal_remainder_len = 0; expected_remainder_len = 0; } read_result = HDread(journal_file_fd, journal_buf, cur_buf_len); if ( read_result != (int)cur_buf_len ) { if ( verbose ) { HDfprintf(stdout, "%s: HDread(j) failed. result = %d, errno = %d.\n", fcn_name, (int)read_result, errno); } failure_mssg2 = "error reading journal file."; pass2 = FALSE; } journal_buf[cur_buf_len] = '\0'; if ( pass2 ) { read_result = HDread(expected_file_fd, expected_buf, cur_buf_len); if ( read_result != (int)cur_buf_len ) { if ( verbose ) { HDfprintf(stdout, "%s: HDread(e) failed. result = %d, errno = %d.\n", fcn_name, (int)read_result, errno); } failure_mssg2 = "error reading expected file."; pass2 = FALSE; } expected_buf[cur_buf_len] = '\0'; } if ( pass2 ) { if ( HDstrcmp(journal_buf, expected_buf) != 0 ) { if ( verbose ) { HDfprintf(stdout, "expected_buf = \"%s\"\n", expected_buf); HDfprintf(stdout, "journal_buf = \"%s\"\n", journal_buf); } failure_mssg2 = "Unexpected journal file contents(2)."; pass2 = FALSE; } } } if ( journal_file_fd != -1 ) { if ( HDclose(journal_file_fd) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDclose(j) failed with errno = %d.\n", fcn_name, errno); } if ( pass2 ) { failure_mssg2 = "Can't close journal file."; pass2 = FALSE; } } } if ( expected_file_fd != -1 ) { if ( HDclose(expected_file_fd) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDclose(e) failed with errno = %d.\n", fcn_name, errno); } if ( pass2 ) { failure_mssg2 = "Can't close expected file."; pass2 = FALSE; } } } return; } /* verify_journal_contents() */ /*------------------------------------------------------------------------- * Function: verify_journal_deleted() * * Purpose: If pass2 is true on entry, stat the target journal file, * and verify that it does not exist. If it does, set * pass2 to FALSE, and set failure_mssg2 to point to an * appropriate failure message. Similarly, if any errors * are detected in this process, set pass2 to FALSE and set * failure_mssg2 to point to an appropriate error message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5//08 * * Modifications: * *------------------------------------------------------------------------- */ static void verify_journal_deleted(const char * journal_file_path_ptr) { const char * fcn_name = "verify_journal_deleted()"; hbool_t verbose = FALSE; h5_stat_t buf; if ( pass2 ) { if ( journal_file_path_ptr == NULL ) { failure_mssg2 = "journal_file_path_ptr NULL on entry?!?", pass2 = FALSE; } } if ( pass2 ) { if ( HDstat(journal_file_path_ptr, &buf) == 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat(%s) succeeded.\n", fcn_name, journal_file_path_ptr); } failure_mssg2 = "journal file not deleted(1)."; pass2 = FALSE; } else if ( errno != ENOENT ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat() failed with unexpected errno = %d.\n", fcn_name, errno); } failure_mssg2 = "journal file not deleted(2)."; pass2 = FALSE; } } return; } /* verify_journal_deleted() */ /*------------------------------------------------------------------------- * Function: verify_journal_empty() * * Purpose: If pass2 is true on entry, stat the target journal file, * and verify that it has length zero. If it is not, set * pass2 to FALSE, and set failure_mssg2 to point to an * appropriate failure message. Similarly, if any errors * are detected in this process, set pass2 to FALSE and set * failure_mssg2 to point to an appropriate error message. * * Do nothing if pass2 is FALSE on entry. * * Return: void * * Programmer: John Mainzer * 5/06/08 * * Modifications: * *------------------------------------------------------------------------- */ static void verify_journal_empty(const char * journal_file_path_ptr) { const char * fcn_name = "verify_journal_empty()"; hbool_t verbose = FALSE; h5_stat_t buf; if ( pass2 ) { if ( journal_file_path_ptr == NULL ) { failure_mssg2 = "journal_file_path_ptr NULL on entry?!?", pass2 = FALSE; } } if ( pass2 ) { if ( HDstat(journal_file_path_ptr, &buf) != 0 ) { if ( verbose ) { HDfprintf(stdout, "%s: HDstat() failed with errno = %d.\n", fcn_name, errno); } failure_mssg2 = "stat() failed on journal file."; pass2 = FALSE; } else { if ( (buf.st_size) > 0 ) { failure_mssg2 = "Empty journal file expected."; pass2 = FALSE; } } } return; } /* verify_journal_empty() */ /*** metadata journaling smoke checks ***/ /*------------------------------------------------------------------------- * Function: mdj_smoke_check_00() * * Purpose: Run a basic smoke check on the metadata journaling * facilities of the metadata cache. Proceed as follows: * * 1) Create a file with journaling enabled. Verify that * journal file is created. * * 2) Using the test entries, simulate a selection of * transactions, which exercise the full range of * metadata cache API which can generate journal entries. * Verify that these transactions are reflected correctly * in the journal. * * 3) Close the hdf5 file, and verify that the journal file * is deleted. Re-open the file with journaling, and * do a transaction or two just to verify that the * journaling is working. * * 4) Close the file, and verify that the journal is deleted. * * 5) Re-open the file with journaling disabled. Do a * transaction or two, and verify that the transactions * took place, and that there is no journal file. * * 6) Enable journaling on the open file. Do a transaction * or two to verify that journaling is working. * * 7) Disable journaling on the open file. Verify that the * journal file has been deleted. * * 8) Close and delete the file. * * Return: void * * Programmer: John Mainzer * 3/11/08 * * Changes: None. * *------------------------------------------------------------------------- */ static void mdj_smoke_check_00(void) { const char * fcn_name = "mdj_smoke_check_00()"; const char * testfiles[] = { "testfiles/cache2_journal_sc00_000.jnl", "testfiles/cache2_journal_sc00_001.jnl", "testfiles/cache2_journal_sc00_002.jnl", "testfiles/cache2_journal_sc00_003.jnl", "testfiles/cache2_journal_sc00_004.jnl", "testfiles/cache2_journal_sc00_005.jnl", "testfiles/cache2_journal_sc00_006.jnl", "testfiles/cache2_journal_sc00_007.jnl", "testfiles/cache2_journal_sc00_008.jnl", "testfiles/cache2_journal_sc00_009.jnl", "testfiles/cache2_journal_sc00_010.jnl", "testfiles/cache2_journal_sc00_011.jnl", "testfiles/cache2_journal_sc00_012.jnl", "testfiles/cache2_journal_sc00_013.jnl", "testfiles/cache2_journal_sc00_014.jnl", "testfiles/cache2_journal_sc00_015.jnl", "testfiles/cache2_journal_sc00_016.jnl", "testfiles/cache2_journal_sc00_017.jnl", "testfiles/cache2_journal_sc00_018.jnl", NULL }; char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; hbool_t testfile_missing = FALSE; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; hbool_t update_architypes = FALSE; herr_t result; int cp = 0; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; H5AC2_jnl_config_t jnl_config; TESTING("mdj smoke check 00 -- general coverage"); pass2 = TRUE; /***********************************************************************/ /* 1) Create a file with cache configuration set to enable journaling. */ /***********************************************************************/ /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (1).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( verbose ) { HDfprintf(stdout, "%s: filename = \"%s\".\n", fcn_name, filename); } /* setup the journal file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, sizeof(journal_filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (2).\n"; } else if ( strlen(journal_filename) >= H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { pass2 = FALSE; failure_mssg2 = "journal file name too long.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( verbose ) { HDfprintf(stdout, "%s: journal filename = \"%s\".\n", fcn_name, journal_filename); } /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, &file_ptr, &cache_ptr, FALSE); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /********************************************************************/ /* 2) Using the test entries, simulate a selection of transactions, */ /* which exercise the full range of metadata cache API calls */ /* that can generate journal entries. Verify that these */ /* transactions are reflected correctly in the journal. */ /********************************************************************/ /* a) First a quick check to see if we can do anything */ begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.0"); insert_entry2(file_ptr, 0, 1, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, 0, 0); unprotect_entry2(file_ptr, 0, 0, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.0"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[0]); } if ( file_exists(testfiles[0]) ) { verify_journal_contents(journal_filename, testfiles[0]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* b) Verify that a sequence of cache operation that do not dirty * any entry do not result in any journal activity. */ begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.1"); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 0); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 1); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 2); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 1, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); protect_entry_ro2(file_ptr, TINY_ENTRY_TYPE, 3); protect_entry_ro2(file_ptr, TINY_ENTRY_TYPE, 3); protect_entry_ro2(file_ptr, TINY_ENTRY_TYPE, 3); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.1"); flush_journal(cache_ptr); verify_journal_empty(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* c) Verify that the most recently dirtied entry get to the head of * the transaction list (and thus appears as the last entry in the * transaction). */ begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.1"); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 0); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 1); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 2); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 3); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 4); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 4, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 5); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 5, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 3); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, TINY_ENTRY_TYPE, 1); unprotect_entry2(file_ptr, TINY_ENTRY_TYPE, 1, FALSE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.1"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[1]); } if ( file_exists(testfiles[1]) ) { verify_journal_contents(journal_filename, testfiles[1]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* d) Mix up some protect/unprotect calls with renames. Do this with * different orders to make things interesting. */ begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.2"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4, TRUE, H5C2__NO_FLAGS_SET); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 2, FALSE); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 3, FALSE); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[2]); } if ( file_exists(testfiles[2]) ) { verify_journal_contents(journal_filename, testfiles[2]); } else { testfile_missing = TRUE; } begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.2"); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 3, TRUE); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 2, TRUE); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[3]); } if ( file_exists(testfiles[3]) ) { verify_journal_contents(journal_filename, testfiles[3]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* e-1) Start by pinning a selection of entries... */ begin_trans(cache_ptr, verbose, (uint64_t)3, "transaction 3.2"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 2, FALSE, H5C2__PIN_ENTRY_FLAG); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 3, TRUE, H5C2__PIN_ENTRY_FLAG); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 4, FALSE, H5C2__PIN_ENTRY_FLAG); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 5, TRUE, H5C2__PIN_ENTRY_FLAG); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6, FALSE, H5C2__PIN_ENTRY_FLAG); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7, TRUE, H5C2__PIN_ENTRY_FLAG); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)3, "transaction 3.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[4]); } if ( file_exists(testfiles[4]) ) { verify_journal_contents(journal_filename, testfiles[4]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* e-2) ... then use the H5C2_mark_pinned_or_protected_entry_dirty() * call to mark a variety of protected, pinned, and pinned and * protected entries dirty. Also rename some pinned entries. */ begin_trans(cache_ptr, verbose, (uint64_t)4, "transaction 4.2"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9); mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 0); mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 1); mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 2); mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 3); mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 6); mark_pinned_or_protected_entry_dirty2(file_ptr, MICRO_ENTRY_TYPE, 7); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 4, FALSE); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 5, FALSE); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 6, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 7, TRUE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 8, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 9, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)4, "transaction 4.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[5]); } if ( file_exists(testfiles[5]) ) { verify_journal_contents(journal_filename, testfiles[5]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* e-3) ...finally, upin all the pinned entries, with an undo of the * previous rename in the middle. */ begin_trans(cache_ptr, verbose, (uint64_t)5, "transaction 5.2"); unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 2); unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 3); unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 4); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 4, TRUE); rename_entry2(cache_ptr, MICRO_ENTRY_TYPE, 5, TRUE); unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 5); unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 6); unpin_entry2(file_ptr, MICRO_ENTRY_TYPE, 7); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)5, "transaction 5.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[6]); } if ( file_exists(testfiles[6]) ) { verify_journal_contents(journal_filename, testfiles[6]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* f-1) Pin a bunch more entries -- make them variable size, as we need * to test resizing. In passing, pin some of the entries using * the H5C2_pin_ptrotected_entry() call. */ begin_trans(cache_ptr, verbose, (uint64_t)6, "transaction 6.2"); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 6); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 7); pin_protected_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); pin_protected_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1, TRUE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2, FALSE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3, TRUE, H5C2__NO_FLAGS_SET); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, FALSE, H5C2__PIN_ENTRY_FLAG); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, TRUE, H5C2__PIN_ENTRY_FLAG); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 6, FALSE, H5C2__PIN_ENTRY_FLAG); unprotect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, H5C2__PIN_ENTRY_FLAG); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)6, "transaction 6.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[7]); } if ( file_exists(testfiles[7]) ) { verify_journal_contents(journal_filename, testfiles[7]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* f-2) Now resize a selection of pinned and unpinned entries via * protect/unprotect pairs, H5C2_resize_pinned_entry() and * H5C2_mark_pinned_entry_dirty(). */ begin_trans(cache_ptr, verbose, (uint64_t)7, "transaction 7.2"); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 0, H5C2__SIZE_CHANGED_FLAG, ((VARIABLE_ENTRY_SIZE / 16) * 15)); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 1, H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, ((VARIABLE_ENTRY_SIZE / 16) * 14)); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 2, H5C2__SIZE_CHANGED_FLAG, ((VARIABLE_ENTRY_SIZE / 16) * 13)); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 3, H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, ((VARIABLE_ENTRY_SIZE / 16) * 12)); resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, ((VARIABLE_ENTRY_SIZE / 16) * 11)); resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, ((VARIABLE_ENTRY_SIZE / 16) * 10)); mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE, ((VARIABLE_ENTRY_SIZE / 16) * 9)); mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, ((VARIABLE_ENTRY_SIZE / 16) * 8)); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)7, "transaction 7.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[8]); } if ( file_exists(testfiles[8]) ) { verify_journal_contents(journal_filename, testfiles[8]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* f-3) Now put all the sizes back, and also rename all the entries. */ begin_trans(cache_ptr, verbose, (uint64_t)8, "transaction 8.2"); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 0, FALSE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 0, H5C2__SIZE_CHANGED_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 1, FALSE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 1, H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 2, FALSE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 2, H5C2__SIZE_CHANGED_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 3, FALSE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 3, H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 4, FALSE); resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 5, FALSE); resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 6, FALSE); mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 7, FALSE); mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, VARIABLE_ENTRY_SIZE); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)8, "transaction 8.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[9]); } if ( file_exists(testfiles[9]) ) { verify_journal_contents(journal_filename, testfiles[9]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* f-4) Finally, rename all the entries back to their original locations, * and unpin all the pinned entries. */ begin_trans(cache_ptr, verbose, (uint64_t)9, "transaction 9.2"); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 0, TRUE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 0); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 0, H5C2__SIZE_CHANGED_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 1, TRUE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 1); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 1, H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 2, TRUE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 2); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 2, H5C2__SIZE_CHANGED_FLAG|H5C2__UNPIN_ENTRY_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 3, TRUE); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 3); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 3, H5C2__SIZE_CHANGED_FLAG|H5C2__DIRTIED_FLAG|H5C2__UNPIN_ENTRY_FLAG, VARIABLE_ENTRY_SIZE); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 4, TRUE); resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4, VARIABLE_ENTRY_SIZE); unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 4); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 5, TRUE); resize_pinned_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5, VARIABLE_ENTRY_SIZE); unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 5); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE); mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 6, TRUE, VARIABLE_ENTRY_SIZE); unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 6); rename_entry2(cache_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE); mark_pinned_entry_dirty2(file_ptr, VARIABLE_ENTRY_TYPE, 7, TRUE, VARIABLE_ENTRY_SIZE); unpin_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 7); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)9, "transaction 9.2"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[10]); } if ( file_exists(testfiles[10]) ) { verify_journal_contents(journal_filename, testfiles[10]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* g) verify that the journaling code handles a cascade of changes * caused when the serialization of an entry causes dirties, resizes, * and/or resizes of other entries. * * g-1) Load several entries of VARIABLE_ENTRY_TYPE into the cache, and * set their sizes to values less than the maximum. */ begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.3"); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 10); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 10, H5C2__SIZE_CHANGED_FLAG, ((VARIABLE_ENTRY_SIZE / 4) * 1)); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 11); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 11, H5C2__SIZE_CHANGED_FLAG, ((VARIABLE_ENTRY_SIZE / 4) * 2)); protect_entry2(file_ptr, VARIABLE_ENTRY_TYPE, 12); unprotect_entry_with_size_change2(file_ptr, VARIABLE_ENTRY_TYPE, 12, H5C2__SIZE_CHANGED_FLAG, ((VARIABLE_ENTRY_SIZE / 4) * 3)); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.3"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[11]); } if ( file_exists(testfiles[11]) ) { verify_journal_contents(journal_filename, testfiles[11]); } else { testfile_missing = TRUE; } /* g-2) Now setup flush operations on some entries to dirty, resize, * and/or rename other entries. When these entries are dirtied * in a transaction, the associated flush operations should be * triggered and appear in the journal. * * In case you need a score card, in what follows, I set up the * following dependencies: * * (MICRO_ENTRY_TYPE, 20) dirties (MICRO_ENTRY_TYPE, 30) * * (MICRO_ENTRY_TYPE, 21) renames, resizes, and dirties: * (VARIABLE_ENTRY_TYPE, 10) * (VARIABLE_ENTRY_TYPE, 13) * * (MICRO_ENTRY_TYPE, 22) resizes (VARIABLE_ENTRY_TYPE, 11) * (VARIABLE_ENTRY_TYPE, 12) * * (MICRO_ENTRY_TYPE, 23) renames (VARIABLE_ENTRY_TYPE, 10) * (VARIABLE_ENTRY_TYPE, 13) * to their original locations * * (MICRO_ENTRY_TYPE, 24) dirties (MICRO_ENTRY_TYPE, 21) * * (MICRO_ENTRY_TYPE, 25) dirties (MICRO_ENTRY_TYPE, 22) * (MICRO_ENTRY_TYPE, 23) * */ add_flush_op2(MICRO_ENTRY_TYPE, 20, FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 30, FALSE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 21, FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 10, FALSE, VARIABLE_ENTRY_SIZE); add_flush_op2(MICRO_ENTRY_TYPE, 21, FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 10, FALSE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 21, FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 10, FALSE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 21, FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 13, FALSE, VARIABLE_ENTRY_SIZE/4); add_flush_op2(MICRO_ENTRY_TYPE, 21, FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 13, FALSE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 21, FLUSH_OP__DIRTY, VARIABLE_ENTRY_TYPE, 13, FALSE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 22, FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 11, FALSE, VARIABLE_ENTRY_SIZE); add_flush_op2(MICRO_ENTRY_TYPE, 22, FLUSH_OP__RESIZE, VARIABLE_ENTRY_TYPE, 12, FALSE, VARIABLE_ENTRY_SIZE); add_flush_op2(MICRO_ENTRY_TYPE, 23, FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 10, TRUE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 23, FLUSH_OP__RENAME, VARIABLE_ENTRY_TYPE, 13, TRUE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 24, FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 21, FALSE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 25, FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 22, FALSE, 0); add_flush_op2(MICRO_ENTRY_TYPE, 25, FLUSH_OP__DIRTY, MICRO_ENTRY_TYPE, 23, FALSE, 0); /* g-3) Start with a simple check -- dirty (MICRO_ENTRY_TYPE, 20), * which should also dirty (MICRO_ENTRY_TYPE, 30) when * (MICRO_ENTRY_TYPE, 20) is serialized at transaction close. */ begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.3"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 20); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 20, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.3"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[12]); } if ( file_exists(testfiles[12]) ) { verify_journal_contents(journal_filename, testfiles[12]); } else { testfile_missing = TRUE; } /* g-4) Now dirty (MICRO_ENTRY_TYPE, 24), which dirties * (MICRO_ENTRY_TYPE, 21), which dirties, resizes, and * renames (VARIABLE_ENTRY_TYPE, 10) and (VARIABLE_ENTRY_TYPE, 13) */ begin_trans(cache_ptr, verbose, (uint64_t)3, "transaction 3.3"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 24); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 24, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)3, "transaction 3.3"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[13]); } if ( file_exists(testfiles[13]) ) { verify_journal_contents(journal_filename, testfiles[13]); } else { testfile_missing = TRUE; } /* g-4) Now dirty (MICRO_ENTRY_TYPE, 25), which dirties * (MICRO_ENTRY_TYPE, 22) and (MICRO_ENTRY_TYPE, 23), which * in turn resize (VARIABLE_ENTRY_TYPE, 11) and * (VARIABLE_ENTRY_TYPE, 12), and rename (VARIABLE_ENTRY_TYPE, 10) * and (VARIABLE_ENTRY_TYPE, 13) back to their original locations. */ begin_trans(cache_ptr, verbose, (uint64_t)4, "transaction 4.3"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 25); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 25, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)4, "transaction 4.3"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[14]); } if ( file_exists(testfiles[14]) ) { verify_journal_contents(journal_filename, testfiles[14]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* h) Dirty an entry, and then expunge it. Entry should not appear * in the journal. Do this twice -- first with only the expunge * entry in the transaction, and a second time with other entries * involved. * * Note that no journal file will be written until the first * entry, so start with a transaction that generates some data. */ begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.4"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 39); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 39, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.4"); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); begin_trans(cache_ptr, verbose, (uint64_t)2, "transaction 2.4"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 40); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 40, TRUE, H5C2__NO_FLAGS_SET); expunge_entry2(file_ptr, MICRO_ENTRY_TYPE, 40); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)2, "transaction 2.4"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[15]); } if ( file_exists(testfiles[15]) ) { verify_journal_contents(journal_filename, testfiles[15]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); begin_trans(cache_ptr, verbose, (uint64_t)3, "transaction 3.4"); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 41); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 41, TRUE, H5C2__NO_FLAGS_SET); expunge_entry2(file_ptr, MICRO_ENTRY_TYPE, 41); protect_entry2(file_ptr, MICRO_ENTRY_TYPE, 42); unprotect_entry2(file_ptr, MICRO_ENTRY_TYPE, 42, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)3, "transaction 3.4"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[16]); } if ( file_exists(testfiles[16]) ) { verify_journal_contents(journal_filename, testfiles[16]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /************************************************************/ /* 3) Close the hdf5 file, and verify that the journal file */ /* is deleted. Re-open the file with journaling, and */ /* do a transaction or two just to verify that the */ /* journaling is working. */ /************************************************************/ /* a) Close the hdf5 file. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "temporary H5Fclose() failed.\n"; } else { file_id = -1; file_ptr = NULL; cache_ptr = NULL; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* b) Verify that the journal file has been deleted. */ verify_journal_deleted(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* c) Re-open the hdf5 file. */ open_existing_file_for_journaling(filename, journal_filename, &file_id, &file_ptr, &cache_ptr); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* d) do a transaction or to to verify that journaling is working. */ begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.5"); insert_entry2(file_ptr, 0, 1, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, 0, 0); unprotect_entry2(file_ptr, 0, 0, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.5"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[17]); } if ( file_exists(testfiles[17]) ) { verify_journal_contents(journal_filename, testfiles[17]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /**************************************************************/ /* 4) Close the file, and verify that the journal is deleted. */ /**************************************************************/ /* Close the hdf5 file. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "temporary H5Fclose() failed.\n"; } else { file_id = -1; file_ptr = NULL; cache_ptr = NULL; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* b) Verify that the journal file has been deleted. */ verify_journal_deleted(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /************************************************************/ /* 5) Re-open the file with journaling disabled. Do a */ /* transaction or two, and verify that the transactions */ /* took place, and that there is no journal file. */ /************************************************************/ /* re-open the file without journaling enabled */ open_existing_file_without_journaling(filename, &file_id, &file_ptr, &cache_ptr); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* do a transaction to verify that journaling is disabled. * * Note that we will only get a transaction number of zero if * journaling is disabled -- thus the following begin/end trans * calls should fail if journaling is enabled. */ begin_trans(cache_ptr, verbose, (uint64_t)0, "transaction 1.6"); insert_entry2(file_ptr, 0, 10, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, 0, 0); unprotect_entry2(file_ptr, 0, 0, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)0, "transaction 1.6"); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( ( pass2 ) && ( cache_ptr->mdj_enabled ) ) { pass2 = FALSE; failure_mssg2 = "journaling is enabled?!?!(1).\n"; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* note that flush_journal() will throw an exception if journaling * is not enabled, so we don't call it here. Instead, just call * verify_journal_deleted() to verify that there is no journal file. */ verify_journal_deleted(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /************************************************************/ /* 6) Enable journaling on the open file. Do a transaction */ /* or two to verify that journaling is working. */ /************************************************************/ /* now enable journaling */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = TRUE; strcpy(jnl_config.journal_file_path, journal_filename); jnl_config.journal_recovered = FALSE; jnl_config.jbrb_buf_size = (8 * 1024); jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = FALSE; jnl_config.jbrb_human_readable = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /* do a transaction or to to verify that journaling is working. */ begin_trans(cache_ptr, verbose, (uint64_t)1, "transaction 1.7"); insert_entry2(file_ptr, 0, 20, FALSE, H5C2__NO_FLAGS_SET); protect_entry2(file_ptr, 0, 0); unprotect_entry2(file_ptr, 0, 0, TRUE, H5C2__NO_FLAGS_SET); end_trans(file_ptr, cache_ptr, verbose, (uint64_t)1, "transaction 1.7"); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[18]); } if ( file_exists(testfiles[18]) ) { verify_journal_contents(journal_filename, testfiles[18]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /************************************************************/ /* 7) Disable journaling on the open file. Verify that the */ /* journal file has been deleted. */ /************************************************************/ /* disable journaling */ if ( pass2 ) { jnl_config.enable_journaling = FALSE; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); verify_journal_deleted(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /*********************************/ /* 8) Close and delete the file. */ /*********************************/ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fclose(file_id) failed.\n"; } } HDremove(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { PASSED(); if ( testfile_missing ) { puts(" WARNING: One or more missing test files."); fflush(stdout); } } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* mdj_smoke_check_00() */ /*------------------------------------------------------------------------- * Function: mdj_smoke_check_01() * * Purpose: Run a cut down version of smoke_check_1 in cache2.c, with * journaling enabled. Check the journal files generated, * and verify that the journal output matches the architype * test files. Skip the comparison and generate a warning * if an architype file is missing. * * Return: void * * Programmer: John Mainzer * 5/19/08 * * Changes: None. * *------------------------------------------------------------------------- */ static void mdj_smoke_check_01(void) { const char * fcn_name = "mdj_smoke_check_01()"; const char * testfiles[] = { "testfiles/cache2_journal_sc01_000.jnl", "testfiles/cache2_journal_sc01_001.jnl", "testfiles/cache2_journal_sc01_002.jnl", "testfiles/cache2_journal_sc01_003.jnl", "testfiles/cache2_journal_sc01_004.jnl", NULL }; char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; hbool_t testfile_missing = FALSE; hbool_t show_progress = FALSE; hbool_t dirty_inserts = FALSE; hbool_t verbose = FALSE; hbool_t update_architypes = FALSE; int dirty_unprotects = FALSE; int dirty_destroys = FALSE; hbool_t display_stats = FALSE; int32_t lag = 10; int cp = 0; int32_t max_index = 128; uint64_t trans_num = 0; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; TESTING("mdj smoke check 01 -- jrnl clean ins, prot, unprot, del, ren"); pass2 = TRUE; /********************************************************************/ /* Create a file with cache configuration set to enable journaling. */ /********************************************************************/ /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (1).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( verbose ) { HDfprintf(stdout, "%s: filename = \"%s\".\n", fcn_name, filename); } /* setup the journal file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, sizeof(journal_filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (2).\n"; } else if ( strlen(journal_filename) >= H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { pass2 = FALSE; failure_mssg2 = "journal file name too long.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( verbose ) { HDfprintf(stdout, "%s: journal filename = \"%s\".\n", fcn_name, journal_filename); } /* clean out any existing journal file */ HDremove(journal_filename); /* Unfortunately, we get different journal output depending on the * file driver, as at present we are including the end of address * space in journal entries, and the end of address space seems to * be in part a function of the file driver. * * Thus, if we want to use the core file driver when available, we * will either have to remove the end of address space from the * journal entries, get the different file drivers to aggree on * end of address space, or maintain different sets of architype * files for the different file drivers. */ setup_cache_for_journaling(filename, journal_filename, &file_id, &file_ptr, &cache_ptr, FALSE); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /******************************************/ /* Run a small, fairly simple stress test */ /******************************************/ trans_num = 0; jrnl_row_major_scan_forward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ FALSE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* do_renames */ TRUE, /* rename_to_main_addr */ FALSE, /* do_destroys */ TRUE, /* do_mult_ro_protects */ TRUE, /* dirty_destroys */ dirty_destroys, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[0]); } if ( file_exists(testfiles[0]) ) { verify_journal_contents(journal_filename, testfiles[0]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); trans_num = 0; if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_row_major_scan_backward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ FALSE, /* do_inserts */ FALSE, /* dirty_inserts */ dirty_inserts, /* do_renames */ TRUE, /* rename_to_main_addr */ TRUE, /* do_destroys */ FALSE, /* do_mult_ro_protects */ TRUE, /* dirty_destroys */ dirty_destroys, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[1]); } if ( file_exists(testfiles[1]) ) { verify_journal_contents(journal_filename, testfiles[1]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); trans_num = 0; if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_row_major_scan_forward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ FALSE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* do_renames */ TRUE, /* rename_to_main_addr */ FALSE, /* do_destroys */ TRUE, /* do_mult_ro_protects */ TRUE, /* dirty_destroys */ dirty_destroys, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[2]); } if ( file_exists(testfiles[2]) ) { verify_journal_contents(journal_filename, testfiles[2]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ trans_num = 0; verify_journal_empty(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_col_major_scan_forward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ TRUE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[3]); } if ( file_exists(testfiles[3]) ) { verify_journal_contents(journal_filename, testfiles[3]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); trans_num = 0; if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_col_major_scan_backward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ TRUE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[4]); } if ( file_exists(testfiles[4]) ) { verify_journal_contents(journal_filename, testfiles[4]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /****************************************************/ /* Close and discard the file and the journal file. */ /****************************************************/ takedown_cache_after_journaling(file_id, filename, journal_filename, FALSE); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); verify_clean2(); verify_unprotected2(); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { PASSED(); if ( testfile_missing ) { puts(" WARNING: One or more missing test files."); fflush(stdout); } } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* mdj_smoke_check_01() */ /*------------------------------------------------------------------------- * Function: mdj_smoke_check_02() * * Purpose: Run a cut down version of smoke_check_2 in cache2.c, with * journaling enabled. Check the journal files generated, * and verify that the journal output matches the architype * test files. Skip the comparison and generate a warning * if an architype file is missing. * * Return: void * * Programmer: John Mainzer * 5/19/08 * * Changes: None. * *------------------------------------------------------------------------- */ static void mdj_smoke_check_02(void) { const char * fcn_name = "mdj_smoke_check_02()"; const char * testfiles[] = { "testfiles/cache2_journal_sc02_000.jnl", "testfiles/cache2_journal_sc02_001.jnl", "testfiles/cache2_journal_sc02_002.jnl", "testfiles/cache2_journal_sc02_003.jnl", "testfiles/cache2_journal_sc02_004.jnl", NULL }; char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; hbool_t testfile_missing = FALSE; hbool_t show_progress = FALSE; hbool_t dirty_inserts = TRUE; hbool_t verbose = FALSE; hbool_t update_architypes = FALSE; int dirty_unprotects = TRUE; int dirty_destroys = TRUE; hbool_t display_stats = FALSE; int32_t lag = 10; int cp = 0; int32_t max_index = 128; uint64_t trans_num = 0; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; TESTING("mdj smoke check 02 -- jrnl dirty ins, prot, unprot, del, ren"); pass2 = TRUE; /********************************************************************/ /* Create a file with cache configuration set to enable journaling. */ /********************************************************************/ /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (1).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( verbose ) { HDfprintf(stdout, "%s: filename = \"%s\".\n", fcn_name, filename); } /* setup the journal file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, sizeof(journal_filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (2).\n"; } else if ( strlen(journal_filename) >= H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { pass2 = FALSE; failure_mssg2 = "journal file name too long.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( verbose ) { HDfprintf(stdout, "%s: journal filename = \"%s\".\n", fcn_name, journal_filename); } /* clean out any existing journal file */ HDremove(journal_filename); /* Unfortunately, we get different journal output depending on the * file driver, as at present we are including the end of address * space in journal entries, and the end of address space seems to * be in part a function of the file driver. * * Thus, if we want to use the core file driver when available, we * will either have to remove the end of address space from the * journal entries, get the different file drivers to aggree on * end of address space, or maintain different sets of architype * files for the different file drivers. */ setup_cache_for_journaling(filename, journal_filename, &file_id, &file_ptr, &cache_ptr, FALSE); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /******************************************/ /* Run a small, fairly simple stress test */ /******************************************/ trans_num = 0; jrnl_row_major_scan_forward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ FALSE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* do_renames */ TRUE, /* rename_to_main_addr */ FALSE, /* do_destroys */ TRUE, /* do_mult_ro_protects */ TRUE, /* dirty_destroys */ dirty_destroys, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[0]); } if ( file_exists(testfiles[0]) ) { verify_journal_contents(journal_filename, testfiles[0]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); trans_num = 0; if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_row_major_scan_backward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ FALSE, /* do_inserts */ FALSE, /* dirty_inserts */ dirty_inserts, /* do_renames */ TRUE, /* rename_to_main_addr */ TRUE, /* do_destroys */ FALSE, /* do_mult_ro_protects */ TRUE, /* dirty_destroys */ dirty_destroys, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[1]); } if ( file_exists(testfiles[1]) ) { verify_journal_contents(journal_filename, testfiles[1]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); trans_num = 0; if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_row_major_scan_forward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ FALSE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* do_renames */ TRUE, /* rename_to_main_addr */ FALSE, /* do_destroys */ FALSE, /* do_mult_ro_protects */ TRUE, /* dirty_destroys */ dirty_destroys, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[2]); } if ( file_exists(testfiles[2]) ) { verify_journal_contents(journal_filename, testfiles[2]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ trans_num = 0; verify_journal_empty(journal_filename); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_col_major_scan_forward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ TRUE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[3]); } if ( file_exists(testfiles[3]) ) { verify_journal_contents(journal_filename, testfiles[3]); } else { testfile_missing = TRUE; } flush_cache2(file_ptr, FALSE, FALSE, FALSE); /* resets transaction number */ verify_journal_empty(journal_filename); trans_num = 0; if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); jrnl_col_major_scan_backward2(/* file_ptr */ file_ptr, /* max_index */ max_index, /* lag */ lag, /* verbose */ verbose, /* reset_stats */ TRUE, /* display_stats */ display_stats, /* display_detailed_stats */ TRUE, /* do_inserts */ TRUE, /* dirty_inserts */ dirty_inserts, /* dirty_unprotects */ dirty_unprotects, /* trans_num */ trans_num); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); flush_journal(cache_ptr); if ( update_architypes ) { copy_file(journal_filename, testfiles[4]); } if ( file_exists(testfiles[4]) ) { verify_journal_contents(journal_filename, testfiles[4]); } else { testfile_missing = TRUE; } if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); /****************************************************/ /* Close and discard the file and the journal file. */ /****************************************************/ takedown_cache_after_journaling(file_id, filename, journal_filename, FALSE); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); verify_clean2(); verify_unprotected2(); if ( show_progress ) HDfprintf(stdout, "%s:%d cp = %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { PASSED(); if ( testfile_missing ) { puts(" WARNING: One or more missing test files."); fflush(stdout); } } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* mdj_smoke_check_02() */ /*------------------------------------------------------------------------- * Function: mdj_api_example_test * * Purpose: Verify that the example code for using the metadata * journaling works as expected * * This example demonstrates enabling journaling at file * creation time, and enabling journaling on an open file. It * also demonstrates disabling journaling both manualy during a * computation and automatically at file close. Finally, * it demonstrates the use of H5Fflush() to keep the journal * file from becoming too long. * * We begin by creating an hdf5 file with journaling enabled. * * The inital calls to TESTING(), SKIPPED(), h5_fixname(), * HDremove(), the initialization of pass2, and the like are all * part of the HDF5 test framework, and may be largely ignored. * In your application, the only point here is that you will * have to set up the paths to your data file and journal * file. Further, the journal file must not exist before * the hdf5 file is opened, as hdf5 will refuse to overwrite * a journal file. * * With these preliminaries dealt with, we allocate a * file access property list (FAPL). Journaling uses some * recent extensions to the superblock, so the first step * is to set the library version to latest via a call to * H5Pset_libver_bounds(). * * Next, we must set up the journaling property. We could * do this in several ways, but in this example we will do * this by using H5Pget_jnl_config() to get the default * journaling configuration, modifing it, and then using * H5Pset_jnl_config() to replace the default with our * configuration. See the comments in the code for the * particulars -- note that we must set the version field of * the H5AC2_jnl_config_t before we call H5Pget_jnl_config(). * * After setting up the FAPL, we create the file as usual. * Journaling will be enabled with configuration as specified. * * With file created and journaling running we then go off * and do what we want -- in this example we set up a selection * of chunked data sets. Note that these data sets (and our * access pattern) are chosen to maximize the amount of dirty * metadata generated. In your application, you will want to * do just the opposite if possible. * * After the data sets are created, we then shut down journaling * and then re-enable it via the H5Fget_jnl_config() and * H5Fset_jnl_config() calls. Note that when we re-enable * journaling via the H5Fset_jnl_config() call, we don't need * to set all the fields in the H5AC2_jnl_config_t, since we * are re-using the configuration we obtained via the * H5Fget_jnl_config() call. If we had opened the file without * journaling, and then wanted to enable journaling, we would * have had to set up the fields of the H5AC2_jnl_config_t in * much the same way we did earlier in the example. We would * also have had to create the file initially with the latest * format (using H5Pset_libver_bounds()). * * Having re-enabled journaling, we then proceed to write to * our data sets. Again, please not that our write strategy * (round robin and small chunks) is designed to maximize * dirty metadata generation and load on the metadata cache. * In your application, you should try to do just the opposite * if possible. * * However, since we are maximizing dirty metadata generation, * the journal file will grow quickly. This can be a problem, * so from time to time we force truncation of the journal file * via a call to H5Fflush(). This call flushes the hdf5 file, * and then truncates the journal file, as the contents of the * journal becomes irrelvant after the metadata journal is * flushed. * * After writing data to our data sets, we then to a number of * reads. We could turn off journaling here, as we are not * modifying the file. But since we are not generating any * dirty metadata, we aren't generating any journal entries * either -- so it really doesn't matter. * * Finally, we close the hdf5 file. Since journaling is enabled, * the call to H5Fclose() will flush the journal, flush the * metadata cache, truncate the journal, mark the file as not * having journaling in progress, and then delete the journal * file as part of the close. * * Return: void * * Programmer: John Mainzer * 12/14/08 * * Modifications: * * None. * *------------------------------------------------------------------------- */ #define CHUNK_SIZE 10 #define DSET_SIZE (40 * CHUNK_SIZE) #define NUM_DSETS 6 #define NUM_RANDOM_ACCESSES 200000 static void mdj_api_example_test(void) { const char * fcn_name = "mdj_api_example_test()"; char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; hbool_t valid_chunk; hbool_t report_progress = FALSE; hid_t fapl_id = -1; hid_t file_id = -1; hid_t dataspace_id = -1; hid_t filespace_ids[NUM_DSETS]; hid_t memspace_id = -1; hid_t dataset_ids[NUM_DSETS]; hid_t properties; char dset_name[64]; int i, j, k, l, m, n; int progress_counter; herr_t status; hsize_t dims[2]; hsize_t a_size[2]; hsize_t offset[2]; hsize_t chunk_size[2]; int data_chunk[CHUNK_SIZE][CHUNK_SIZE]; H5AC2_jnl_config_t jnl_config_0; H5AC2_jnl_config_t jnl_config_1; TESTING("mdj example code"); if ( skip_long_tests2 > 0 ) { SKIPPED(); HDfprintf(stdout, " Long tests disabled.\n"); return; } pass2 = TRUE; /* Open a file with journaling enabled. */ /* setup the hdf5 file name */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"\nSetting up file name ... "); HDfflush(stdout); } if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed.\n"; } } /* setup the journal file name */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"\nSetting up journal file name ... "); HDfflush(stdout); } if ( pass2 ) { if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, sizeof(journal_filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (2).\n"; } else if ( strlen(journal_filename) >= H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { pass2 = FALSE; failure_mssg2 = "journal file name too long.\n"; } } /* clean out any existing journal file -- must do this as * HDF5 will refuse to overwrite an existing journal file. */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"\nRemoving any existing journal file ... "); HDfflush(stdout); } HDremove(journal_filename); /* create a file access propertly list. */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"\nCreating a FAPL ... "); HDfflush(stdout); } if ( pass2 ) { fapl_id = H5Pcreate(H5P_FILE_ACCESS); if ( fapl_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pcreate() failed.\n"; } } /* need latest version of file format to use journaling */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"\nCalling H5Pset_libver_bounds() on FAPL ... "); HDfflush(stdout); } if ( pass2 ) { if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_libver_bounds() failed.\n"; } } /* Get the current FAPL journaling configuration. This should be * the default, and we could just write a predifined journal configuration * structure to the FAPL directly, but doing it this way shows off the * H5Pget_jnl_config() call, and is less suceptible to API definition * changes. */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "\nCalling H5Pget_jnl_config() on FAPL ... "); HDfflush(stdout); } if ( pass2 ) { jnl_config_0.version = H5AC2__CURR_JNL_CONFIG_VER; status = H5Pget_jnl_config(fapl_id, &jnl_config_0); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_mdc_config() failed.\n"; } } /* Modify the current FAPL journaling configuration to enable * journaling as desired, and then write the revised configuration * back to the FAPL. */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "\nRevising config & calling H5Pset_jnl_config() on FAPL ... "); HDfflush(stdout); } if ( pass2 ) { jnl_config_0.enable_journaling = TRUE; strcpy(jnl_config_0.journal_file_path, journal_filename); /* jnl_config_0.journal_recovered should always be FALSE unless * you are writing a new journal recovery tool, and need to * tell the library that you have recovered the journal and * that the file is now readable. As this field is set to * FALSE by default, we don't touch it here. */ /* the journal buffer size should be some multiple of the block * size of the underlying file system. */ jnl_config_0.jbrb_buf_size = (8 * 1024); /* the number of journal buffers should be either 1 or 2 when * synchronous I/O is used for journal writes. If AIO is used, * the number should be large enough that the write of a buffer * will usually be complete by the time that buffer is needed * again. */ jnl_config_0.jbrb_num_bufs = 2; /* At present we don't support AIO for journal writes, so this * field will be FALSE. */ jnl_config_0.jbrb_use_aio = FALSE; /* At present only human readable journal file are supported * so this field will be TRUE for now. Once it becomes available, * machine readable journal files should be smaller and faster. */ jnl_config_0.jbrb_human_readable = TRUE; status = H5Pset_jnl_config(fapl_id, &jnl_config_0); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_mdc_config() failed.\n"; } } /* Now open the file using the FAPL we have created. */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "\nCreating the HDF5 file using the new FAPL ... "); HDfflush(stdout); } if ( pass2 ) { file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fcreate() failed.\n"; } } /* create the datasets */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"\nCreating datasets ... "); HDfflush(stdout); } if ( pass2 ) { i = 0; while ( ( pass2 ) && ( i < NUM_DSETS ) ) { /* create a dataspace for the chunked dataset */ dims[0] = DSET_SIZE; dims[1] = DSET_SIZE; dataspace_id = H5Screate_simple(2, dims, NULL); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Screate_simple() failed."; } /* set the dataset creation plist to specify that the raw data is * to be partioned into 10X10 element chunks. */ if ( pass2 ) { chunk_size[0] = CHUNK_SIZE; chunk_size[1] = CHUNK_SIZE; properties = H5Pcreate(H5P_DATASET_CREATE); if ( properties < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pcreate() failed."; } } if ( pass2 ) { if ( H5Pset_chunk(properties, 2, chunk_size) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_chunk() failed."; } } /* create the dataset */ if ( pass2 ) { sprintf(dset_name, "/dset%03d", i); dataset_ids[i] = H5Dcreate2(file_id, dset_name, H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, properties, H5P_DEFAULT); if ( dataset_ids[i] < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dcreate() failed."; } } /* get the file space ID */ if ( pass2 ) { filespace_ids[i] = H5Dget_space(dataset_ids[i]); if ( filespace_ids[i] < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dget_space() failed."; } } i++; } } /* just for purposes of demonstration, turn off journaling, and * then turn it back on again. Note that this will force a * flush of the file, and all metadata with it. Turning off * journaling will also cause us to close and discard the * journal file after all metadata is on disk. */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "\nTurning off journaling ... "); HDfflush(stdout); } if ( pass2 ) { jnl_config_1.version = H5AC2__CURR_JNL_CONFIG_VER; status = H5Fget_jnl_config(file_id, &jnl_config_1); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_mdc_config() failed.\n"; } } if ( pass2 ) { jnl_config_1.enable_journaling = FALSE; status = H5Fset_jnl_config(file_id, &jnl_config_1); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_mdc_config() failed.\n"; } } /* Note that here we simply set jnl_config_1.enable_journaling to * TRUE, and pass it back to the HDF5 library via the * H5Fset_jnl_config() call. * * We can do this because jnl_config_1 reflected the current * journaling configuration when we got it from the library * via the H5Fget_jnl_config() call, and H5Fset_mdc_config() * doesn't change the values of any fields. */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "\nTurning journaling back on ... "); HDfflush(stdout); } if ( pass2 ) { jnl_config_1.enable_journaling = TRUE; status = H5Fset_jnl_config(file_id, &jnl_config_1); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_mdc_config() failed.\n"; } } /* create the mem space to be used to read and write chunks */ if ( pass2 ) { dims[0] = CHUNK_SIZE; dims[1] = CHUNK_SIZE; memspace_id = H5Screate_simple(2, dims, NULL); if ( memspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Screate_simple() failed."; } } /* select in memory hyperslab */ if ( pass2 ) { offset[0] = 0; /*offset of hyperslab in memory*/ offset[1] = 0; a_size[0] = CHUNK_SIZE; /*size of hyperslab*/ a_size[1] = CHUNK_SIZE; status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Sselect_hyperslab() failed."; } } if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"Done.\n"); HDfflush(stdout); } /* initialize all datasets on a round robin basis */ i = 0; progress_counter = 0; if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "Initializing datasets "); HDfflush(stdout); } while ( ( pass2 ) && ( i < DSET_SIZE ) ) { j = 0; while ( ( pass2 ) && ( j < DSET_SIZE ) ) { m = 0; while ( ( pass2 ) && ( m < NUM_DSETS ) ) { /* initialize the slab */ for ( k = 0; k < CHUNK_SIZE; k++ ) { for ( l = 0; l < CHUNK_SIZE; l++ ) { data_chunk[k][l] = (DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l; } } /* select on disk hyperslab */ offset[0] = i; /*offset of hyperslab in file*/ offset[1] = j; a_size[0] = CHUNK_SIZE; /*size of hyperslab*/ a_size[1] = CHUNK_SIZE; status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "disk H5Sselect_hyperslab() failed."; } /* write the chunk to file */ status = H5Dwrite(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], H5P_DEFAULT, data_chunk); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dwrite() failed."; } m++; } j += CHUNK_SIZE; } i += CHUNK_SIZE; if ( ( pass2 ) && ( report_progress ) ) { progress_counter += CHUNK_SIZE; if ( progress_counter >= DSET_SIZE / 20 ) { progress_counter = 0; HDfprintf(stdout, "."); HDfflush(stdout); } } /* We are generating a lot of dirty metadata here, all of which * will wind up in the journal file. To keep the journal file * from getting too big (and to make sure the raw data is on * disk, we should do an occasional flush of the HDF5 file. * * This will force all metadata to disk, and cause the journal * file to be truncated. * * On the other hand, it will impose a significant file I/O * overhead, and slow us down. (try it both ways). */ #if 1 /* JRM */ status = H5Fflush(file_id, H5F_SCOPE_GLOBAL); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fflush() failed."; } #endif /* JRM */ } if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout," Done.\n"); /* initializing data sets */ HDfflush(stdout); } /* do random reads on all datasets */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "Doing random reads on all datasets "); HDfflush(stdout); } n = 0; progress_counter = 0; while ( ( pass2 ) && ( n < NUM_RANDOM_ACCESSES ) ) { m = rand() % NUM_DSETS; i = (rand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE; j = (rand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE; /* select on disk hyperslab */ offset[0] = i; /*offset of hyperslab in file*/ offset[1] = j; a_size[0] = CHUNK_SIZE; /*size of hyperslab*/ a_size[1] = CHUNK_SIZE; status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "disk hyperslab create failed."; } /* read the chunk from file */ if ( pass2 ) { status = H5Dread(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], H5P_DEFAULT, data_chunk); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "disk hyperslab create failed."; } } /* validate the slab */ if ( pass2 ) { valid_chunk = TRUE; for ( k = 0; k < CHUNK_SIZE; k++ ) { for ( l = 0; l < CHUNK_SIZE; l++ ) { if ( data_chunk[k][l] != ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l) ) { valid_chunk = FALSE; #if 0 /* this will be useful from time to time -- lets keep it*/ HDfprintf(stdout, "data_chunk[%0d][%0d] = %0d, expect %0d.\n", k, l, data_chunk[k][l], ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)); HDfprintf(stdout, "m = %d, i = %d, j = %d, k = %d, l = %d\n", m, i, j, k, l); #endif } } } if ( ! valid_chunk ) { #if 1 pass2 = FALSE; failure_mssg2 = "slab validation failed."; #else /* as above */ fprintf(stdout, "Chunk (%0d, %0d) in /dset%03d is invalid.\n", i, j, m); #endif } } n++; if ( ( pass2 ) && ( report_progress ) ) { progress_counter++; if ( progress_counter >= NUM_RANDOM_ACCESSES / 20 ) { progress_counter = 0; HDfprintf(stdout, "."); HDfflush(stdout); } } } if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, " Done.\n"); /* random reads on all data sets */ HDfflush(stdout); } /* close the file spaces we are done with */ i = 1; while ( ( pass2 ) && ( i < NUM_DSETS ) ) { if ( H5Sclose(filespace_ids[i]) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Sclose() failed."; } i++; } /* close the datasets we are done with */ i = 1; while ( ( pass2 ) && ( i < NUM_DSETS ) ) { if ( H5Dclose(dataset_ids[i]) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dclose() failed."; } i++; } /* do random reads on data set 0 only */ if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, "Doing random reads on dataset 0 "); HDfflush(stdout); } m = 0; n = 0; progress_counter = 0; while ( ( pass2 ) && ( n < NUM_RANDOM_ACCESSES ) ) { i = (rand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE; j = (rand() % (DSET_SIZE / CHUNK_SIZE)) * CHUNK_SIZE; /* select on disk hyperslab */ offset[0] = i; /*offset of hyperslab in file*/ offset[1] = j; a_size[0] = CHUNK_SIZE; /*size of hyperslab*/ a_size[1] = CHUNK_SIZE; status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "disk hyperslab create failed."; } /* read the chunk from file */ if ( pass2 ) { status = H5Dread(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], H5P_DEFAULT, data_chunk); if ( status < 0 ) { pass2 = FALSE; failure_mssg2 = "disk hyperslab create failed."; } } /* validate the slab */ if ( pass2 ) { valid_chunk = TRUE; for ( k = 0; k < CHUNK_SIZE; k++ ) { for ( l = 0; l < CHUNK_SIZE; l++ ) { if ( data_chunk[k][l] != ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l) ) { valid_chunk = FALSE; } #if 0 /* this will be useful from time to time -- lets keep it */ HDfprintf(stdout, "data_chunk[%0d][%0d] = %0d, expect %0d.\n", k, l, data_chunk[k][l], ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)); #endif } } if ( ! valid_chunk ) { pass2 = FALSE; failure_mssg2 = "slab validation failed."; #if 0 /* as above */ fprintf(stdout, "Chunk (%0d, %0d) in /dset%03d is invalid.\n", i, j, m); #endif } } n++; if ( ( pass2 ) && ( report_progress ) ) { progress_counter++; if ( progress_counter >= NUM_RANDOM_ACCESSES / 20 ) { progress_counter = 0; HDfprintf(stdout, "."); HDfflush(stdout); } } } if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout, " Done.\n"); /* random reads data set 0 */ HDfflush(stdout); } if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"Shutting down ... "); HDfflush(stdout); } /* close file space 0 */ if ( pass2 ) { if ( H5Sclose(filespace_ids[0]) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Sclose(filespace_ids[0]) failed."; } } /* close the data space */ if ( pass2 ) { if ( H5Sclose(dataspace_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Sclose(dataspace) failed."; } } /* close the mem space */ if ( pass2 ) { if ( H5Sclose(memspace_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Sclose(memspace_id) failed."; } } /* close dataset 0 */ if ( pass2 ) { if ( H5Dclose(dataset_ids[0]) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dclose(dataset_ids[0]) failed."; } } /* close the file and delete it */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fclose() failed.\n"; } else if ( HDremove(filename) < 0 ) { pass2 = FALSE; failure_mssg2 = "HDremove() failed.\n"; } } if ( ( pass2 ) && ( report_progress ) ) { HDfprintf(stdout,"Done.\n"); /* shutting down */ HDfflush(stdout); } if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* mdj_api_example_test() */ /*** metatada journaling config block I/O test code ***/ /*------------------------------------------------------------------------- * Function: check_mdj_config_block_IO() * * Purpose: Verify that the functions that read, write, and discard * metadata journaling config blocks operate as they should. * * Return: void * * Programmer: John Mainzer * 3/11/08 * * Modifications: * *------------------------------------------------------------------------- */ static void check_mdj_config_block_IO(void) { const char * fcn_name = "check_mdj_config_block_IO()"; const char * test_path = "/a/full/path"; char filename[512]; hbool_t show_progress = FALSE; int cp = 0; herr_t result; hsize_t block_len = 0; haddr_t block_addr = HADDR_UNDEF; hid_t fapl_id = -1; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; TESTING("metadata journaling config block I/O"); pass2 = TRUE; /* 1) Open a file * * 2) Go through several create, read, and discard cycles. Verify that * the correct information is read back. Use a variety of journal * file path length to ensure that we don't have problems with blocks * with length some multiple of 4. * * 3) Create a metadata journaling configuration block. * * 4) Close the file, and reopen it. * * 5) Read the metadata journaling configuration block, and verify * that it contains the expected data. * * 6) Close and discard the file. * * Note that we don't do any tests to verify that the config block * code fails where expected -- We will do this in a separate test * function if at all. * -- JRM */ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /******************/ /* 1) Open a file */ /******************/ /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[2], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* create a file access propertly list -- this isn't necessary in this * case, but it is how we will open the file when we journal, so we do * it regardless. */ if ( pass2 ) { fapl_id = H5Pcreate(H5P_FILE_ACCESS); if ( fapl_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pcreate() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* call H5Pset_libver_bounds() on the fapl_id */ if ( pass2 ) { if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_libver_bounds() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* create the file using fapl_id */ if ( pass2 ) { file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fcreate() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * to the cache structure */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (1).\n"; } else if ( file_ptr->shared->cache2 == NULL ) { pass2 = FALSE; failure_mssg2 = "can't get cache2 pointer(1).\n"; } else { cache_ptr = file_ptr->shared->cache2; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*************************************************************************/ /* 2) Go through several create, read, and discard cycles. Verify that */ /* the correct information is read back. Use a variety of journal */ /* file path length to ensure that we don't have problems with blocks */ /* with length some multiple of 4. */ /*************************************************************************/ test_mdj_conf_blk_read_write_discard(file_ptr, "a"); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); test_mdj_conf_blk_read_write_discard(file_ptr, "ab"); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); test_mdj_conf_blk_read_write_discard(file_ptr, "abc"); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); test_mdj_conf_blk_read_write_discard(file_ptr, "abcd"); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); test_mdj_conf_blk_read_write_discard(file_ptr, "abcde"); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); test_mdj_conf_blk_read_write_discard(file_ptr, "abcdefghijklmnopqrstuvwxyz"); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /********************************************************/ /* 3) Create a metadata journaling configuration block. */ /********************************************************/ if ( pass2 ) { if ( ( cache_ptr->mdj_file_name_ptr != NULL ) || ( cache_ptr->mdj_conf_block_addr != HADDR_UNDEF ) || ( cache_ptr->mdj_conf_block_len != 0 ) || ( cache_ptr->mdj_conf_block_ptr != NULL ) ) { pass2 = FALSE; failure_mssg2 = "Bad cache config on entry."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { result = H5C2_create_journal_config_block(file_ptr, H5P_DATASET_XFER_DEFAULT, test_path); if ( result != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_create_journal_config_block() failed."; } else { block_addr = cache_ptr->mdj_conf_block_addr; block_len = cache_ptr->mdj_conf_block_len; if ( cache_ptr->mdj_conf_block_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_ptr == NULL after create."; } else if ( cache_ptr->mdj_file_name_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_file_name_ptr == NULL after create."; } else if ( strcmp(test_path, cache_ptr->mdj_file_name_ptr) != 0 ) { pass2 = FALSE; failure_mssg2 = "journal file path mismatch after create."; } else if ( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_addr == HADDR_UNDEF after create."; } else if ( cache_ptr->mdj_conf_block_len == 0 ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_len == 0 after create."; } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*************************************/ /* 4) Close the file, and reopen it. */ /*************************************/ /* close the file. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "file close failed (1)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* open the file r/w using the same FAPL */ if ( pass2 ) { file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl_id); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (3).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * to the cache structure */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (1).\n"; } else if ( file_ptr->shared->cache2 == NULL ) { pass2 = FALSE; failure_mssg2 = "can't get cache2 pointer(1).\n"; } else { cache_ptr = file_ptr->shared->cache2; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*******************************************************************/ /* 5) Read the metadata journaling configuration block, and verify */ /* that it contains the expected data. */ /*******************************************************************/ if ( pass2 ) { H5MM_xfree(cache_ptr->mdj_conf_block_ptr); cache_ptr->mdj_conf_block_addr = HADDR_UNDEF; cache_ptr->mdj_conf_block_len = 0; cache_ptr->mdj_conf_block_ptr = NULL; cache_ptr->mdj_file_name_ptr = NULL; result = H5C2_load_journal_config_block(file_ptr, H5P_DATASET_XFER_DEFAULT, cache_ptr, block_addr, block_len); if ( result != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_load_journal_config_block() failed."; } else { if ( cache_ptr->mdj_conf_block_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_ptr == NULL after load."; } else if ( cache_ptr->mdj_file_name_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_file_name_ptr == NULL after load."; } else if ( strcmp(test_path, cache_ptr->mdj_file_name_ptr ) != 0) { pass2 = FALSE; failure_mssg2 = "journal file path mismatch after load."; } else if ( cache_ptr->mdj_conf_block_addr != block_addr ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_addr != block_addr after load."; } else if ( cache_ptr->mdj_conf_block_len != block_len ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_len != block_len after load."; } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /**********************************/ /* 6) Close and discard the file. */ /**********************************/ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "file close failed (5)."; } else if ( HDremove(filename) < 0 ) { pass2 = FALSE; failure_mssg2 = "HDremove() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } } /* check_mdj_config_block_IO() */ /*------------------------------------------------------------------------- * Function: test_mdj_conf_blk_read_write_discard() * * Purpose: Using the supplied cache and journal file path, create * a metadata journal configuration block, read it and * verify the contents, and then discard it. * * Do nothing if pass2 is false on entry * * Return: void * * Programmer: John Mainzer * 3/13/08 * * Modifications: * *------------------------------------------------------------------------- */ static void test_mdj_conf_blk_read_write_discard(H5F_t * file_ptr, const char * jrnl_file_path) { const char * fcn_name = "test_mdj_conf_blk_read_write_discard()"; H5C2_t * cache_ptr = file_ptr->shared->cache2; hbool_t show_progress = FALSE; int cp = 0; herr_t result; hsize_t block_len = 0; haddr_t block_addr = HADDR_UNDEF; if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( cache_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr NULL on entry."; } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { if ( ( cache_ptr->mdj_file_name_ptr != NULL ) || ( cache_ptr->mdj_conf_block_addr != HADDR_UNDEF ) || ( cache_ptr->mdj_conf_block_len != 0 ) || ( cache_ptr->mdj_conf_block_ptr != NULL ) ) { pass2 = FALSE; failure_mssg2 = "Bad cache config on entry."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { result = H5C2_create_journal_config_block(file_ptr, H5P_DATASET_XFER_DEFAULT, jrnl_file_path); if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( result != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_create_journal_config_block() failed."; } else { block_addr = cache_ptr->mdj_conf_block_addr; block_len = cache_ptr->mdj_conf_block_len; if ( cache_ptr->mdj_conf_block_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_ptr == NULL after create."; } else if ( cache_ptr->mdj_file_name_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_file_name_ptr == NULL after create."; } else if ( strcmp(jrnl_file_path, cache_ptr->mdj_file_name_ptr) != 0 ) { pass2 = FALSE; failure_mssg2 = "journal file path mismatch after create."; } else if ( cache_ptr->mdj_conf_block_addr == HADDR_UNDEF ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_addr == HADDR_UNDEF after create."; } else if ( cache_ptr->mdj_conf_block_len == 0 ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_len == 0 after create."; } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { H5MM_xfree(cache_ptr->mdj_conf_block_ptr); cache_ptr->mdj_conf_block_addr = HADDR_UNDEF; cache_ptr->mdj_conf_block_len = 0; cache_ptr->mdj_conf_block_ptr = NULL; cache_ptr->mdj_file_name_ptr = NULL; result = H5C2_load_journal_config_block(file_ptr, H5P_DATASET_XFER_DEFAULT, cache_ptr, block_addr, block_len); if ( result != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_load_journal_config_block() failed."; } else { if ( cache_ptr->mdj_conf_block_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_ptr == NULL after load."; } else if ( cache_ptr->mdj_file_name_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_file_name_ptr == NULL after load."; } else if ( strcmp(jrnl_file_path, cache_ptr->mdj_file_name_ptr) != 0) { pass2 = FALSE; failure_mssg2 = "journal file path mismatch after load."; } else if ( cache_ptr->mdj_conf_block_addr != block_addr ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_addr != block_addr after load."; } else if ( cache_ptr->mdj_conf_block_len != block_len ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_len != block_len after load."; } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { result = H5C2_discard_journal_config_block(file_ptr, H5P_DATASET_XFER_DEFAULT); if ( result != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_discard_journal_config_block() failed."; } else { if ( cache_ptr->mdj_conf_block_ptr != NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_ptr != NULL after discard."; } else if ( cache_ptr->mdj_file_name_ptr != NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_file_name_ptr != NULL after discard."; } else if ( cache_ptr->mdj_conf_block_addr != HADDR_UNDEF ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_addr != HADDR_UNDEF after discard."; } else if ( cache_ptr->mdj_conf_block_len != 0 ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdj_conf_block_len != 0 after discard."; } } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); return; } /* test_mdj_conf_blk_read_write_discard() */ /*** super block extension related test code ***/ /*------------------------------------------------------------------------- * Function: check_superblock_extensions() * * Purpose: Verify that the super block extensions for tracking * operate as they should. * * Note that this test code will have to be re-worked * once journaling is fully implemented. * * Return: void * * Programmer: John Mainzer * 2/26/08 * * Modifications: * *------------------------------------------------------------------------- */ extern hbool_t H5C2__check_for_journaling; static void check_superblock_extensions(void) { const char * fcn_name = "check_superblock_extensions()"; char filename[512]; hbool_t show_progress = FALSE; haddr_t mdc_jrnl_block_loc = 0x1000; hsize_t mdc_jrnl_block_len = 0x100; int cp = 0; hid_t fapl_id = -1; hid_t file_id = -1; hid_t dataset_id = -1; hid_t dataspace_id = -1; H5F_t * file_ptr = NULL; hsize_t dims[2]; TESTING("superblock extensions"); pass2 = TRUE; /* Verify that the journaling superblock extension performs as * expected. Note that this test will have to be re-written * (or possibly subsumed in another test) once the full journaling * code is up and running. * * For now at least, the test proceeds as follows: * * 1) create a HDF5 file, and verify that journaling is * listed as being off. * * 2) create a dataset in the file, and then close the file * * 3) Open the file again, and verifiy that journaling is still * listed as being off. * * 4) Write data to the superblock marking the file as currently * being journaled, and close the file again. * * 5) Open the file a third time, and verify that the superblock * extension indicates that the file is being journaled. * * 6) Reset the journaling information to indicate that the file * is not being journaled, and close the file again. * * 7) Open the file a fourth time, and verify that the superblock * extension indicates that the file is not being journaled. * * 8) Write data to the superblock, marking the file as being * journaled. Now write different data to the superbloc, that * still marks the file as being journaled. Close the file. * * 9) Re-open the file, and verify that the second write in 8 * above took. * * 10) Write data to the superblock indicating that journaling is * not in progress. Close the file. * * 11) Reopen the file, and verify that journaling is not in * progress. * * 12) Close the file and delete it. */ /********************************************************/ /* 1) create a HDF5 file, and verify that journaling is */ /* listed as being off. */ /********************************************************/ if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[2], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* create a file access propertly list */ if ( pass2 ) { fapl_id = H5Pcreate(H5P_FILE_ACCESS); if ( fapl_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pcreate() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* call H5Pset_libver_bounds() on the fapl_id */ if ( pass2 ) { if ( H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Pset_libver_bounds() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* create the file using fapl_id */ if ( pass2 ) { file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fcreate() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * verify that journaling is disabled. */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (1).\n"; } else if ( file_ptr->shared->mdc_jrnl_enabled ) { pass2 = FALSE; failure_mssg2 = "Journaling enabled on file creation.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /************************************************************/ /* 2) create a dataset in the file, and then close the file */ /************************************************************/ if ( pass2 ) { dims[0] = 4; dims[1] = 6; dataspace_id = H5Screate_simple(2, dims, NULL); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Screate_simple() failed."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { /* Create the dataset. */ dataset_id = H5Dcreate2(file_id, "/dset", H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dcreate2() failed."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { /* close the data set, the data space, and the file */ if ( ( H5Dclose(dataset_id) < 0 ) || ( H5Sclose(dataspace_id) < 0 ) || ( H5Fclose(file_id) < 0 ) ) { pass2 = FALSE; failure_mssg2 = "data set, data space, or file close failed."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /****************************************************************/ /* 3) Open the file again, and verifiy that journaling is still */ /* listed as being off. */ /****************************************************************/ /* open the file r/w using the default FAPL */ if ( pass2 ) { file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (4).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * verify that journaling is disabled. */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (2).\n"; } else if ( file_ptr->shared->mdc_jrnl_enabled ) { pass2 = FALSE; failure_mssg2 = "Journaling enabled on file open (1).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*****************************************************************/ /* 4) Write data to the superblock marking the file as currently */ /* being journaled, and close the file again. */ /*****************************************************************/ /* At present, we just write the super block regardless if the * file is opened read/write. This is ugly, but that is how it * is for now. Thus just go in and modify the journaling fields * of the super block to taste. */ if ( pass2 ) { file_ptr->shared->mdc_jrnl_enabled = TRUE; file_ptr->shared->mdc_jrnl_block_loc = mdc_jrnl_block_loc; file_ptr->shared->mdc_jrnl_block_len = mdc_jrnl_block_len; if ( H5F_super_write_mdj_msg(file_ptr, -1) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5F_super_write_mdj_msg failed (1)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* close the file again. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "file close failed (1)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*****************************************************************/ /* 5) Open the file a third time, and verify that the superblock */ /* extension indicates that the file is being journaled. */ /*****************************************************************/ /* open the file r/w using the default FAPL -- turn off journaling * in progress check during the open. * */ if ( pass2 ) { H5C2__check_for_journaling = FALSE; file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); H5C2__check_for_journaling = TRUE; if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (5).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * verify that journaling is enabled. */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (3).\n"; } else if ( ! file_ptr->shared->mdc_jrnl_enabled ) { pass2 = FALSE; failure_mssg2 = "Journaling disabled on file open (1).\n"; } else if ( file_ptr->shared->mdc_jrnl_block_loc != mdc_jrnl_block_loc ) { pass2 = FALSE; HDfprintf(stdout, "%s: block_loc = %ld (%ld).\n", fcn_name, (long)(file_ptr->shared->mdc_jrnl_block_loc), (long)(mdc_jrnl_block_loc)); failure_mssg2 = "unexpected mdc_jrnl_block_loc(1).\n"; } else if ( file_ptr->shared->mdc_jrnl_block_len != (hsize_t)mdc_jrnl_block_len ) { pass2 = FALSE; failure_mssg2 = "unexpected mdc_jrnl_block_len (1).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*****************************************************************/ /* 6) Reset the journaling information to indicate that the file */ /* is not being journaled, and close the file again. */ /*****************************************************************/ if ( pass2 ) { file_ptr->shared->mdc_jrnl_enabled = FALSE; if ( H5F_super_write_mdj_msg(file_ptr, -1) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5F_super_write_mdj_msg failed (2)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* close the file again. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "file close failed (2)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /******************************************************************/ /* 7) Open the file a fourth time, and verify that the superblock */ /* extension indicates that the file is not being journaled. */ /*******************************************************************/ /* open the file r/w using the default FAPL */ if ( pass2 ) { file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (6).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * verify that journaling is disabled. */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (4).\n"; } else if ( file_ptr->shared->mdc_jrnl_enabled ) { pass2 = FALSE; failure_mssg2 = "Journaling enabled on file open (2).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*******************************************************************/ /* 8) Write data to the superblock, marking the file as being */ /* journaled. Now write different data to the superbloc, that */ /* still marks the file as being journaled. Close the file. */ /*******************************************************************/ if ( pass2 ) { file_ptr->shared->mdc_jrnl_enabled = TRUE; file_ptr->shared->mdc_jrnl_block_loc = mdc_jrnl_block_loc * 2; file_ptr->shared->mdc_jrnl_block_len = mdc_jrnl_block_len * 2; if ( H5F_super_write_mdj_msg(file_ptr, -1) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5F_super_write_mdj_msg failed (3)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { file_ptr->shared->mdc_jrnl_enabled = TRUE; file_ptr->shared->mdc_jrnl_block_loc = mdc_jrnl_block_loc / 2; file_ptr->shared->mdc_jrnl_block_len = mdc_jrnl_block_len / 2; if ( H5F_super_write_mdj_msg(file_ptr, -1) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5F_super_write_mdj_msg failed (4)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* close the file again. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "file close failed (3)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /***************************************************************/ /* 9) Re-open the file, and verify that the second write in 8 */ /* above took. */ /***************************************************************/ /* open the file r/w using the default FAPL -- turn off journaling * in progress check during the open. */ if ( pass2 ) { H5C2__check_for_journaling = FALSE; file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); H5C2__check_for_journaling = TRUE; if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (7).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * verify that journaling is enabled. */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (5).\n"; } else if ( ! file_ptr->shared->mdc_jrnl_enabled ) { pass2 = FALSE; failure_mssg2 = "Journaling disabled on file open (2).\n"; } else if ( file_ptr->shared->mdc_jrnl_block_loc != mdc_jrnl_block_loc / 2 ) { pass2 = FALSE; HDfprintf(stdout, "%s: block_loc = %ld (%ld).\n", fcn_name, (long)(file_ptr->shared->mdc_jrnl_block_loc), (long)(mdc_jrnl_block_loc)); failure_mssg2 = "unexpected mdc_jrnl_block_loc(2).\n"; } else if ( file_ptr->shared->mdc_jrnl_block_len != (hsize_t)mdc_jrnl_block_len / 2 ) { pass2 = FALSE; failure_mssg2 = "unexpected mdc_jrnl_block_len (2).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /******************************************************************/ /* 10) Write data to the superblock indicating that journaling is */ /* not in progress. Close the file. */ /******************************************************************/ if ( pass2 ) { file_ptr->shared->mdc_jrnl_enabled = FALSE; if ( H5F_super_write_mdj_msg(file_ptr, -1) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5F_super_write_mdj_msg failed (5)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* close the file again. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "file close failed (4)."; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*************************************************************/ /* 11) Reopen the file, and verify that journaling is not in */ /* progress. */ /*************************************************************/ /* open the file r/w using the default FAPL */ if ( pass2 ) { file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); if ( file_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fopen() failed (8).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /* get a pointer to the files internal data structure and then * verify that journaling is disabled. */ if ( pass2 ) { file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE); if ( file_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "Can't get file_ptr (6).\n"; } else if ( file_ptr->shared->mdc_jrnl_enabled ) { pass2 = FALSE; failure_mssg2 = "Journaling enabled on file open (3).\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); /*************************************/ /* 12) Close the file and delete it. */ /*************************************/ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "file close failed (5)."; } else if ( HDremove(filename) < 0 ) { pass2 = FALSE; failure_mssg2 = "HDremove() failed.\n"; } } if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } } /* check_superblock_extensions() */ /*************************************************************************** * Function: check_mdjsc_callbacks() * * Purpose: Verify that the registration and deregistration of * metadata journaling status change registration/deregistraion * works correctly. * * Verify that the status change callbacks are called as * they should be, and that the cache is clean when the * callback is called. * * On failure, set pass2 to false, and failure_mssg2 to an * appropriate error string. * * Return: void * * Programmer: John Mainzer * 7/2/08 * **************************************************************************/ static void check_mdjsc_callbacks(void) { const char * fcn_name = "check_mdjsc_callbacks():"; TESTING("metadata journaling status change callbacks"); verify_mdjsc_callback_registration_deregistration(); verify_mdjsc_callback_execution(); verify_mdjsc_callback_error_rejection(); if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* check_mdjsc_callbacks() */ /*************************************************************************** * * Function: test_mdjsc_callback() * * Purpose: Test callback function used to test the metadata * journaling status change callback facility. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static H5C2_t * callback_test_cache_ptr = NULL; static hbool_t callback_test_invalid_cache_ptr = FALSE; static hbool_t callback_test_null_config_ptr = FALSE; static hbool_t callback_test_invalid_config = FALSE; static hbool_t callback_test_null_data_ptr = FALSE; static hbool_t callback_test_cache_is_dirty = FALSE; static int callback_test_null_data_ptr_count = 0; static herr_t test_mdjsc_callback(H5C2_mdj_config_t * config_ptr, hid_t dxpl_id, void * data_ptr) { if ( config_ptr == NULL ) { callback_test_null_config_ptr = TRUE; } if ( ( callback_test_cache_ptr == NULL ) || ( callback_test_cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { callback_test_invalid_cache_ptr = TRUE; } else if ( callback_test_cache_ptr->slist_len > 0 ) { callback_test_cache_is_dirty = TRUE; } else if ( ( callback_test_cache_ptr != NULL ) && ( callback_test_cache_ptr->mdj_enabled != config_ptr->enable_journaling ) ) { callback_test_invalid_config = TRUE; } if ( data_ptr == NULL ) { callback_test_null_data_ptr = TRUE; callback_test_null_data_ptr_count++; } else { *((int *)data_ptr) += 1; } return SUCCEED; } /* test_mdjsc_callback() */ /*************************************************************************** * * Function: deregister_mdjsc_callback() * * Purpose: Attempt to deregister the metadata journaling status change * callback with the supplied index, and verify that the * deregistration took place. * * If any error is detected, set pass2 t FALSE, and set the * failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static void deregister_mdjsc_callback(H5F_t * file_ptr, H5C2_t * cache_ptr, int32_t idx) { herr_t result; if ( pass2 ) { if ( ( file_ptr == NULL ) || ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { pass2 = FALSE; failure_mssg2 = "deregister_mdjsc_callback(): bad param(s) on entry."; } } if ( pass2 ) { result = H5AC2_deregister_mdjsc_callback(file_ptr, idx); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5AC2_deregister_mdjsc_callback() failed."; } verify_mdjsc_callback_deregistered(cache_ptr, idx); } return; } /* deregister_mdjsc_callback() */ /*************************************************************************** * * Function: register_mdjsc_callback() * * Purpose: Attempt to register the supplied metadata journaling * status change callback, and verify that the registration * took. * * If any error is detected, set pass2 t FALSE, and set the * failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static void register_mdjsc_callback(H5F_t * file_ptr, H5C2_t * cache_ptr, H5C2_mdj_status_change_func_t fcn_ptr, void * data_ptr, int32_t * idx_ptr) { herr_t result; H5C2_mdj_config_t init_config; if ( pass2 ) { if ( ( file_ptr == NULL ) || ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) || ( fcn_ptr == NULL ) || ( idx_ptr == NULL ) ) { pass2 = FALSE; failure_mssg2 = "register_mdjsc_callback(): bad param(s) on entry."; } } if ( pass2 ) { result = H5AC2_register_mdjsc_callback(file_ptr, fcn_ptr, data_ptr, idx_ptr, &init_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5AC2_register_mdjsc_callback() failed."; } else if ( init_config.enable_journaling != cache_ptr->mdj_enabled ) { pass2 = FALSE; failure_mssg2 = "init_config.enable_journaling != cache_ptr->mdj_enabled"; } verify_mdjsc_callback_registered(cache_ptr, fcn_ptr, data_ptr, *idx_ptr); } return; } /* register_mdjsc_callback() */ /*************************************************************************** * * Function: verify_mdjsc_table_config() * * Purpose: Verify that the mdjsc callback table is configured as * specified. * * If all is as it should be, do nothing. * * If anything is not as it should be, set pass2 to FALSE, * and set failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static void verify_mdjsc_table_config(H5C2_t * cache_ptr, int32_t table_len, int32_t num_entries, int32_t max_idx_in_use, hbool_t * free_entries) { const char * fcn_name = "verify_mdjsc_table_config()"; hbool_t show_progress = FALSE; int cp = 0; if ( show_progress ) HDfprintf(stdout, "%s:%d: %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { pass2 = FALSE; failure_mssg2 = "bad cache_ptr."; } } if ( show_progress ) HDfprintf(stdout, "%s:%d: %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { if ( cache_ptr->mdjsc_cb_tbl == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdjsc_cb_tbl == NULL."; } } if ( show_progress ) HDfprintf(stdout, "%s:%d: %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { if ( cache_ptr->mdjsc_cb_tbl_len != table_len ) { pass2 = FALSE; failure_mssg2 = "mdjsc callback table len mismatch"; #if 1 /* JRM */ HDfprintf(stdout, "cache_ptr->mdjsc_cb_tbl_len = %d(%d).\n", cache_ptr->mdjsc_cb_tbl_len, table_len); #endif /* JRM */ } else if ( cache_ptr->num_mdjsc_cbs != num_entries ) { pass2 = FALSE; failure_mssg2 = "mdjsc callback table num entries mismatch"; } else if ( cache_ptr->mdjsc_cb_tbl_max_idx_in_use != max_idx_in_use ) { #if 1 /* JRM */ HDfprintf(stdout, "cache_ptr->mdjsc_cb_tbl_max_idx_in_use = %d(%d)\n", cache_ptr->mdjsc_cb_tbl_max_idx_in_use, max_idx_in_use); #endif /* JRM */ pass2 = FALSE; failure_mssg2 = "mdjsc callback table max idx in use mismatch"; } } if ( show_progress ) HDfprintf(stdout, "%s:%d: %d.\n", fcn_name, pass2, cp++); if ( ( pass2 ) && ( free_entries ) ) { int32_t i = 0; int32_t j; H5C2_mdjsc_record_t * record_ptr = NULL; while ( ( pass2 ) && ( i < table_len ) ) { if ( free_entries[i] ) { if ( (( (cache_ptr->mdjsc_cb_tbl)[i]).fcn_ptr != NULL) || (((cache_ptr->mdjsc_cb_tbl)[i]).data_ptr != NULL) ) { pass2 = FALSE; failure_mssg2 = "mdjsc callback table entry in use that should be free"; } } else { /* recall that the data_ptr can be NULL when an entry is * in use. */ if ( ((cache_ptr->mdjsc_cb_tbl)[i]).fcn_ptr == NULL ) { pass2 = FALSE; failure_mssg2 = "mdjsc callback table entry free that shoult be in use"; } } i++; } if ( show_progress ) HDfprintf(stdout, "%s:%d: %d.\n", fcn_name, pass2, cp++); i = 0; j = cache_ptr->mdjsc_cb_tbl_fl_head; while ( ( pass2 ) && ( i < (table_len - num_entries) ) && ( j >= 0 ) && ( j < table_len ) ) { record_ptr = &((cache_ptr->mdjsc_cb_tbl)[j]); if ( ( record_ptr->fcn_ptr != NULL ) || ( record_ptr->data_ptr != NULL ) ) { pass2 = FALSE; failure_mssg2 = "mdjsc callback table free list entry in use."; } i++; j = record_ptr->fl_next; } if ( show_progress ) HDfprintf(stdout, "%s:%d: %d.\n", fcn_name, pass2, cp++); if ( pass2 ) { if ( i != (table_len - num_entries) ) { pass2 = FALSE; failure_mssg2 = "mdjsc callback table free list shorter than expected."; #if 1 /* JRM */ HDfprintf(stdout, "i = %d (%d - %d = %d)\n", i, table_len, num_entries, (table_len - num_entries)); HDfprintf(stdout, "cache_ptr->mdjsc_cb_tbl_fl_head = %d.\n", cache_ptr->mdjsc_cb_tbl_fl_head); #endif /* JRM */ } else if ( ( record_ptr != NULL ) && ( record_ptr->fl_next != -1 ) ) { pass2 = FALSE; failure_mssg2 = "mdjsc callback table free list longer than expected."; } } } if ( show_progress ) HDfprintf(stdout, "%s:%d: %d -- done.\n", fcn_name, pass2, cp++); return; } /* verify_mdjsc_table_config() */ /*************************************************************************** * * Function: verify_mdjsc_callback_deregistered() * * Purpose: Verify that the suplied mdjsc callback is registerd * in the metadata journaling status change callback table * at the specified index and with the specified data ptr. * * If all is as it should be, do nothing. * * If anything is not as it should be, set pass2 to FALSE, * and set failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static void verify_mdjsc_callback_deregistered(H5C2_t * cache_ptr, int32_t idx) { if ( pass2 ) { if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { pass2 = FALSE; failure_mssg2 = "bad cache_ptr."; } } if ( pass2 ) { if ( cache_ptr->mdjsc_cb_tbl == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdjsc_cb_tbl == NULL."; } } if ( ( pass2 ) && ( idx < cache_ptr->mdjsc_cb_tbl_len ) ) { if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).fcn_ptr != NULL ) { pass2 = FALSE; failure_mssg2 = "fcn_ptr mismatch"; } else if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).data_ptr != NULL ) { pass2 = FALSE; failure_mssg2 = "data_ptr mismatch"; } } return; } /* verify_mdjsc_callback_deregistered() */ /*************************************************************************** * * Function: verify_mdjsc_callback_registered() * * Purpose: Verify that the suplied mdjsc callback is registerd * in the metadata journaling status change callback table * at the specified index and with the specified data ptr. * * If all is as it should be, do nothing. * * If anything is not as it should be, set pass2 to FALSE, * and set failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static void verify_mdjsc_callback_registered(H5C2_t * cache_ptr, H5C2_mdj_status_change_func_t fcn_ptr, void * data_ptr, int32_t idx) { if ( pass2 ) { if ( ( cache_ptr == NULL ) || ( cache_ptr->magic != H5C2__H5C2_T_MAGIC ) ) { pass2 = FALSE; failure_mssg2 = "bad cache_ptr."; } } if ( pass2 ) { if ( ( fcn_ptr == NULL ) || ( idx < 0 ) ) { pass2 = FALSE; failure_mssg2 = "bad fcn_ptr and/or negative idx."; } } if ( pass2 ) { if ( cache_ptr->mdjsc_cb_tbl == NULL ) { pass2 = FALSE; failure_mssg2 = "cache_ptr->mdjsc_cb_tbl == NULL."; } } if ( pass2 ) { if ( cache_ptr->mdjsc_cb_tbl_len <= idx ) { pass2 = FALSE; failure_mssg2 = "idx out of range."; } } if ( pass2 ) { if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).fcn_ptr != fcn_ptr ) { pass2 = FALSE; failure_mssg2 = "fcn_ptr mismatch"; } else if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).data_ptr != data_ptr ) { pass2 = FALSE; failure_mssg2 = "data_ptr mismatch"; } else if ( ((cache_ptr->mdjsc_cb_tbl)[idx]).fl_next != -1 ) { pass2 = FALSE; failure_mssg2 = "fl_next != -1"; } } return; } /* verify_mdjsc_callback_registered() */ /*************************************************************************** * * Function: verify_mdjsc_callback_error_rejection() * * Purpose: Run a variety of tests to verify that the metadata * journaling status change callbacks registration and * de-registration routines will fail on obviously * invalid input. * * If anything is not as it should be, set pass2 to FALSE, * and set failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/20/08 * **************************************************************************/ static void verify_mdjsc_callback_error_rejection(void) { const char * fcn_name = "verify_mdjsc_callback_error_rejection():"; char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; const int max_callbacks = 1024 * H5C2__MIN_MDJSC_CB_TBL_LEN; int counters[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; int i; int expected_num_entries = 0; int expected_table_len = H5C2__MIN_MDJSC_CB_TBL_LEN; int expected_max_idx = -1; int32_t indicies[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; hbool_t free_entries[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; int cp = 0; herr_t result; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; for ( i = 0; i < max_callbacks; i++ ) { counters[i] = 0; free_entries[i] = TRUE; indicies[i] = -1; } /* 1) Create a file with journaling enabled. * * 2) Attempt to register callbacks with a variety of NULL * pointers supplied for parameters other than data_ptr. * All attempts should fail. * * 3) Attempt to deregister a callback in an empty callback table. * Should fail * * 4) Register a few callbacks. Attempt to deregister non-existant * callbacks with indicies both inside and outside the range * of indicies currently represented in the table. All should * fail. * * 5) Deregister the remaining callbacks, and then close and delete * the file. */ /* 1) Create a file with journaling enabled. */ /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (1).\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, pass2, cp++); HDfflush(stdout); } if ( verbose ) { HDfprintf(stdout, "%s filename = \"%s\".\n", fcn_name, filename); HDfflush(stdout); } /* setup the journal file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, sizeof(journal_filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (2).\n"; } else if ( strlen(journal_filename) >= H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { pass2 = FALSE; failure_mssg2 = "journal file name too long.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( verbose ) { HDfprintf(stdout, "%s journal filename = \"%s\".\n", fcn_name, journal_filename); HDfflush(stdout); } /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, &file_ptr, &cache_ptr, FALSE); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 2) Attempt to register callbacks with a variety of NULL * pointers supplied for parameters other than data_ptr. * All attempts should fail. */ if ( pass2 ) { result = H5AC2_register_mdjsc_callback(NULL, test_mdjsc_callback, NULL, &(indicies[0]), NULL); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_register_mdjsc_callback() succeeded with NULL file_ptr"; } } if ( pass2 ) { result = H5AC2_register_mdjsc_callback(file_ptr, NULL, NULL, &(indicies[0]), NULL); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_register_mdjsc_callback() succeeded with NULL fcn_ptr"; } } if ( pass2 ) { result = H5AC2_register_mdjsc_callback(file_ptr, test_mdjsc_callback, NULL, NULL, NULL); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_register_mdjsc_callback() succeeded with NULL idx_ptr"; } } /* 3) Attempt to deregister a callback in an empty callback table. * Should fail */ if ( pass2 ) { result = H5AC2_deregister_mdjsc_callback(NULL, 0); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_deregister_mdjsc_callback() succeeded with NULL file_ptr"; } } if ( pass2 ) { result = H5AC2_deregister_mdjsc_callback(file_ptr, 0); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_deregister_mdjsc_callback() succeeded with invld idx(1)"; } } /* 4) Register a few callbacks. Attempt to deregister non-existant * callbacks with indicies both inside and outside the range * of indicies currently represented in the table. All should * fail. */ register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[0]), &(indicies[0])); register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, NULL, &(indicies[1])); register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[2]), &(indicies[2])); free_entries[0] = FALSE; free_entries[1] = FALSE; free_entries[2] = FALSE; expected_num_entries += 3; expected_max_idx = 2; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( pass2 ) { result = H5AC2_deregister_mdjsc_callback(file_ptr, 3); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_deregister_mdjsc_callback() succeeded with invld idx(2)"; } } if ( pass2 ) { result = H5AC2_deregister_mdjsc_callback(file_ptr, -1); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_deregister_mdjsc_callback() succeeded with invld idx(3)"; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( pass2 ) { result = H5AC2_deregister_mdjsc_callback(file_ptr, 1); if ( result != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_deregister_mdjsc_callback() failed with valid idx"; } else { free_entries[1] = TRUE; expected_num_entries--; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } if ( pass2 ) { result = H5AC2_deregister_mdjsc_callback(file_ptr, -1); if ( result == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5AC2_deregister_mdjsc_callback() succeeded with invld idx(4)"; } } /* 5) Deregister the remaining callbacks, and then close and delete * the file. */ deregister_mdjsc_callback(file_ptr, cache_ptr, 0); deregister_mdjsc_callback(file_ptr, cache_ptr, 2); free_entries[0] = TRUE; free_entries[2] = TRUE; expected_num_entries -= 2; expected_max_idx = -1; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); /* Close the file, and tidy up. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fclose() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* delete the HDF5 file and journal file */ #if 1 HDremove(filename); HDremove(journal_filename); #endif if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d done.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } return; } /* verify_mdjsc_callback_error_rejection() */ /*************************************************************************** * * Function: verify_mdjsc_callback_execution() * * Purpose: Run a variety of tests to verify that the metadata * journaling status change callbacks are actually performed, * at the correct time, and that the expected data is passed * to the callback function. * * If anything is not as it should be, set pass2 to FALSE, * and set failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static void verify_mdjsc_callback_execution(void) { const char * fcn_name = "verify_mdjsc_callback_execution():"; char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; const int max_callbacks = 1024 * H5C2__MIN_MDJSC_CB_TBL_LEN; int counters[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; int i; int expected_num_entries = 0; int expected_table_len = H5C2__MIN_MDJSC_CB_TBL_LEN; int expected_max_idx = -1; int32_t indicies[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; hbool_t free_entries[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; int cp = 0; herr_t result; hid_t dataset_id = -1; hid_t dataspace_id = -1; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; hsize_t dims[2]; H5AC2_jnl_config_t jnl_config; for ( i = 0; i < max_callbacks; i++ ) { counters[i] = 0; free_entries[i] = TRUE; indicies[i] = -1; } /* 1) Create a file with journaling enabled. * * 2) Register a callback. * * 3) Disable journaling. Verify that the callback is called, * that it gets the correct data, and that the cache is clean * at time of call. * * 4) Enable journaling again. Verify that the callback is * called, that it gets the correct data, and that the cache * is clear at time of call. * * 5) Perform some writes to the file. * * 6) Disable journaling. Verify that the callback is called, * that it gets the correct data, and that the cache is * clean at time of call. * * 7) Perform some more writes to the file. * * 8) Enable journaling again. Verify that the callback is * called, that it gets the correct data, and that the cache * is clear at time of call. * * 9) Deregister the callback, and close the file. Recall that * all metadata journaling status change callbacks must * deregister before the metadata cache is destroyed. * * 10) Re-open the file with journaling disabled, and register * several callbacks. Ensure that at least one has NULL * data_ptr. * * 11) Enable journaling. Verify that the callbacks are called. * * 12) Perform some writes to the file. * * 13) Register a great number of callbacks. * * 14) Disable journaling. Verify that the callbacks are called. * * 15) Deregister some of the callbacks. * * 16) Enable journaling. Verify that the remaining callbacks are * called. * * 17) Deregister the remaining callbacks, and then close and delete * the file. */ /* 1) Create a file with journaling enabled. */ /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (1).\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, pass2, cp++); HDfflush(stdout); } if ( verbose ) { HDfprintf(stdout, "%s filename = \"%s\".\n", fcn_name, filename); HDfflush(stdout); } /* setup the journal file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, sizeof(journal_filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (2).\n"; } else if ( strlen(journal_filename) >= H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { pass2 = FALSE; failure_mssg2 = "journal file name too long.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( verbose ) { HDfprintf(stdout, "%s journal filename = \"%s\".\n", fcn_name, journal_filename); HDfflush(stdout); } /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, &file_ptr, &cache_ptr, FALSE); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 2) Register a callback. */ register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[0]), &(indicies[0])); free_entries[0] = FALSE; expected_num_entries++; expected_max_idx = 0; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 3) Disable journaling. Verify that the callback is called, * that it gets the correct data, and that the cache is clean * at time of call. */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = FALSE; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { counters[0] = 0; callback_test_cache_ptr = cache_ptr; callback_test_invalid_cache_ptr = FALSE; callback_test_null_config_ptr = FALSE; callback_test_invalid_config = FALSE; callback_test_null_data_ptr = FALSE; callback_test_cache_is_dirty = FALSE; callback_test_null_data_ptr_count = 0; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { if ( counters[0] != 1 ) { pass2 = FALSE; failure_mssg2 = "incorrect number of callback calls(1)."; } else if ( callback_test_cache_is_dirty ) { pass2 = FALSE; failure_mssg2 = "callback found dirty cache(1)."; } else if ( ( callback_test_invalid_cache_ptr ) || ( callback_test_null_config_ptr ) || ( callback_test_invalid_config ) || ( callback_test_null_data_ptr ) || ( callback_test_null_data_ptr_count != 0 ) ) { pass2 = FALSE; failure_mssg2 = "Bad parameter(s) to callback(1)."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 4) Enable journaling again. Verify that the callback is * called, that it gets the correct data, and that the cache * is clear at time of call. */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = TRUE; strcpy(jnl_config.journal_file_path, journal_filename); jnl_config.journal_recovered = FALSE; jnl_config.jbrb_buf_size = (8 * 1024); jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = FALSE; jnl_config.jbrb_human_readable = TRUE; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { counters[0] = 0; callback_test_cache_ptr = cache_ptr; callback_test_invalid_cache_ptr = FALSE; callback_test_null_config_ptr = FALSE; callback_test_invalid_config = FALSE; callback_test_null_data_ptr = FALSE; callback_test_cache_is_dirty = FALSE; callback_test_null_data_ptr_count = 0; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { if ( counters[0] != 1 ) { pass2 = FALSE; failure_mssg2 = "incorrect number of callback calls(2)."; } else if ( callback_test_cache_is_dirty ) { pass2 = FALSE; failure_mssg2 = "callback found dirty cache(2)."; } else if ( ( callback_test_invalid_cache_ptr ) || ( callback_test_null_config_ptr ) || ( callback_test_invalid_config ) || ( callback_test_null_data_ptr ) ) { pass2 = FALSE; failure_mssg2 = "Bad parameter(s) to callback(2)."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 5) Perform some writes to the file. */ if ( pass2 ) { dims[0] = 4; dims[1] = 6; dataspace_id = H5Screate_simple(2, dims, NULL); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Screate_simple() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { /* Create the dataset. */ dataset_id = H5Dcreate2(file_id, "/dset0", H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dcreate2() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { /* close the data set, and the data space */ if ( ( H5Dclose(dataset_id) < 0 ) || ( H5Sclose(dataspace_id) < 0 ) ) { pass2 = FALSE; failure_mssg2 = "data set, or data space close failed."; } } if ( pass2 ) { if ( cache_ptr->slist_len <= 0 ) { pass2 = FALSE; failure_mssg2 = "cache isnt' dirty?!?"; } } /* 6) Disable journaling. Verify that the callback is called, * that it gets the correct data, and that the cache is * clean at time of call. */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = FALSE; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { counters[0] = 0; callback_test_cache_ptr = cache_ptr; callback_test_invalid_cache_ptr = FALSE; callback_test_null_config_ptr = FALSE; callback_test_invalid_config = FALSE; callback_test_null_data_ptr = FALSE; callback_test_cache_is_dirty = FALSE; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { if ( counters[0] != 1 ) { pass2 = FALSE; failure_mssg2 = "incorrect number of callback calls(3)."; } else if ( callback_test_cache_is_dirty ) { pass2 = FALSE; failure_mssg2 = "callback found dirty cache(3)."; } else if ( ( callback_test_invalid_cache_ptr ) || ( callback_test_null_config_ptr ) || ( callback_test_invalid_config ) || ( callback_test_null_data_ptr ) ) { pass2 = FALSE; failure_mssg2 = "Bad parameter(s) to callback(3)."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 7) Perform some more writes to the file. */ if ( pass2 ) { dims[0] = 6; dims[1] = 8; dataspace_id = H5Screate_simple(2, dims, NULL); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Screate_simple() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { /* Create the dataset. */ dataset_id = H5Dcreate2(file_id, "/dset1", H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dcreate2() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { /* close the data set, and the data space */ if ( ( H5Dclose(dataset_id) < 0 ) || ( H5Sclose(dataspace_id) < 0 ) ) { pass2 = FALSE; failure_mssg2 = "data set, or data space close failed."; } } if ( pass2 ) { if ( cache_ptr->slist_len <= 0 ) { pass2 = FALSE; failure_mssg2 = "cache isnt' dirty?!?"; } } /* 8) Enable journaling again. Verify that the callback is * called, that it gets the correct data, and that the cache * is clear at time of call. */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = TRUE; strcpy(jnl_config.journal_file_path, journal_filename); jnl_config.journal_recovered = FALSE; jnl_config.jbrb_buf_size = (8 * 1024); jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = FALSE; jnl_config.jbrb_human_readable = TRUE; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { counters[0] = 0; callback_test_cache_ptr = cache_ptr; callback_test_invalid_cache_ptr = FALSE; callback_test_null_config_ptr = FALSE; callback_test_invalid_config = FALSE; callback_test_null_data_ptr = FALSE; callback_test_cache_is_dirty = FALSE; callback_test_null_data_ptr_count = 0; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { if ( counters[0] != 1 ) { pass2 = FALSE; failure_mssg2 = "incorrect number of callback calls(4)."; } else if ( callback_test_cache_is_dirty ) { pass2 = FALSE; failure_mssg2 = "callback found dirty cache(4)."; } else if ( ( callback_test_invalid_cache_ptr ) || ( callback_test_null_config_ptr ) || ( callback_test_invalid_config ) || ( callback_test_null_data_ptr ) ) { pass2 = FALSE; failure_mssg2 = "Bad parameter(s) to callback(4)."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 9) Deregister the callback, and close the file. Recall that * all metadata journaling status change callbacks must * deregister before the metadata cache is destroyed. */ deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[0]); indicies[0] = -1; free_entries[0] = TRUE; expected_num_entries = 0; expected_max_idx = -1; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( file_id >= 0 ) { if ( H5Fclose(file_id) < 0 ) { if ( pass2 ) { pass2 = FALSE; failure_mssg2 = "file close failed."; } } } if ( show_progress ) { HDfprintf(stdout, "%s%d *cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 10) Re-open the file with journaling disabled, and register * several callbacks. Ensure that at least one has NULL * data_ptr. */ open_existing_file_without_journaling(filename, &file_id, &file_ptr, &cache_ptr); register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[0]), &(indicies[0])); register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, NULL, &(indicies[1])); register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[2]), &(indicies[2])); free_entries[0] = FALSE; free_entries[1] = FALSE; free_entries[2] = FALSE; expected_num_entries += 3; expected_max_idx = 2; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); /* 11) Enable journaling. Verify that the callbacks are called. */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = TRUE; strcpy(jnl_config.journal_file_path, journal_filename); jnl_config.journal_recovered = FALSE; jnl_config.jbrb_buf_size = (8 * 1024); jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = FALSE; jnl_config.jbrb_human_readable = TRUE; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { counters[0] = 0; callback_test_cache_ptr = cache_ptr; callback_test_invalid_cache_ptr = FALSE; callback_test_null_config_ptr = FALSE; callback_test_invalid_config = FALSE; callback_test_null_data_ptr = FALSE; callback_test_cache_is_dirty = FALSE; callback_test_null_data_ptr_count = 0; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { if ( ( counters[0] != 1 ) && ( counters[1] != 0 ) && ( counters[2] != 1 ) && ( counters[3] != 0 ) ) { pass2 = FALSE; failure_mssg2 = "incorrect number of callback calls(5)."; } else if ( callback_test_cache_is_dirty ) { pass2 = FALSE; failure_mssg2 = "callback found dirty cache(5)."; } else if ( ( callback_test_invalid_cache_ptr ) || ( callback_test_null_config_ptr ) || ( callback_test_invalid_config ) ) { pass2 = FALSE; failure_mssg2 = "Bad parameter(s) to callback(5)."; } else if ( ( ! callback_test_null_data_ptr ) || ( callback_test_null_data_ptr_count != 1 ) ) { pass2 = FALSE; failure_mssg2 = "incorrect null data_ptr callbacks.(5)"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 12) Perform some writes to the file. */ if ( pass2 ) { dims[0] = 8; dims[1] = 10; dataspace_id = H5Screate_simple(2, dims, NULL); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Screate_simple() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { /* Create the dataset. */ dataset_id = H5Dcreate2(file_id, "/dset2", H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if ( dataspace_id < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Dcreate2() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { /* close the data set, and the data space */ if ( ( H5Dclose(dataset_id) < 0 ) || ( H5Sclose(dataspace_id) < 0 ) ) { pass2 = FALSE; failure_mssg2 = "data set, or data space close failed."; } } if ( pass2 ) { if ( cache_ptr->slist_len <= 0 ) { pass2 = FALSE; failure_mssg2 = "cache isnt' dirty?!?"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 13) Register a great number of callbacks. */ for ( i = 3; i < max_callbacks; i++ ) { if ( ( pass2 ) && ( free_entries[i] ) ) { register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[i]), &(indicies[i])); HDassert( indicies[i] == i ); free_entries[i] = FALSE; expected_num_entries++; if ( i > expected_max_idx ) { expected_max_idx = i; } if ( expected_num_entries > expected_table_len ) { expected_table_len *= 2; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } HDassert( expected_num_entries == max_callbacks ); HDassert( expected_max_idx == (max_callbacks - 1) ); HDassert( expected_table_len == max_callbacks ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 14) Disable journaling. Verify that the callbacks are called. */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = FALSE; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { for ( i = 0; i < max_callbacks; i++ ) { counters[i] = 0; } callback_test_cache_ptr = cache_ptr; callback_test_invalid_cache_ptr = FALSE; callback_test_null_config_ptr = FALSE; callback_test_invalid_config = FALSE; callback_test_null_data_ptr = FALSE; callback_test_cache_is_dirty = FALSE; callback_test_null_data_ptr_count = 0; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { int max_counter = 0; int counter_sum = 0; for ( i = 0; i < max_callbacks; i++ ) { if ( counters[i] > max_counter ) { max_counter = counters[i]; } counter_sum += counters[i]; } if ( ( counters[1] != 0 ) || ( max_counter != 1 ) || ( counter_sum != max_callbacks - 1 ) ) { pass2 = FALSE; failure_mssg2 = "incorrect number of callback calls(6)."; } else if ( callback_test_cache_is_dirty ) { pass2 = FALSE; failure_mssg2 = "callback found dirty cache(6)."; } else if ( ( callback_test_invalid_cache_ptr ) || ( callback_test_null_config_ptr ) || ( callback_test_invalid_config ) ) { pass2 = FALSE; failure_mssg2 = "Bad parameter(s) to callback(6)."; } else if ( ( ! callback_test_null_data_ptr ) || ( callback_test_null_data_ptr_count != 1 ) ) { pass2 = FALSE; failure_mssg2 = "incorrect null data_ptr callbacks.(6)"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 15) Deregister some of the callbacks. */ /* working from the top downwards, de-register all entries with * indicies not divisible by 8. */ for ( i = max_callbacks - 1; i >= 0; i-- ) { if ( ( pass2 ) && ( ! free_entries[i] ) && ( (i % 8) != 0 ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); while ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } HDassert( expected_num_entries == max_callbacks / 8 ); HDassert( expected_max_idx == (max_callbacks - 8) ); HDassert( expected_table_len == max_callbacks ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 16) Enable journaling. Verify that the remaining callbacks are * called. */ if ( pass2 ) { jnl_config.version = H5AC2__CURR_JNL_CONFIG_VER; result = H5Fget_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fget_jnl_config() failed.\n"; } /* set journaling config fields to taste */ jnl_config.enable_journaling = TRUE; strcpy(jnl_config.journal_file_path, journal_filename); jnl_config.journal_recovered = FALSE; jnl_config.jbrb_buf_size = (8 * 1024); jnl_config.jbrb_num_bufs = 2; jnl_config.jbrb_use_aio = FALSE; jnl_config.jbrb_human_readable = TRUE; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { for ( i = 0; i < max_callbacks; i++ ) { counters[i] = 0; } callback_test_cache_ptr = cache_ptr; callback_test_invalid_cache_ptr = FALSE; callback_test_null_config_ptr = FALSE; callback_test_invalid_config = FALSE; callback_test_null_data_ptr = FALSE; callback_test_cache_is_dirty = FALSE; callback_test_null_data_ptr_count = 0; result = H5Fset_jnl_config(file_id, &jnl_config); if ( result < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fset_jnl_config() failed.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( pass2 ) { int max_counter = 0; int counter_sum = 0; for ( i = 0; i < max_callbacks; i++ ) { if ( counters[i] > max_counter ) { max_counter = counters[i]; } counter_sum += counters[i]; } if ( ( max_counter != 1 ) || ( counter_sum != ( max_callbacks / 8 ) ) ) { pass2 = FALSE; failure_mssg2 = "incorrect number of callback calls(7)."; } else if ( callback_test_cache_is_dirty ) { pass2 = FALSE; failure_mssg2 = "callback found dirty cache(7)."; } else if ( ( callback_test_invalid_cache_ptr ) || ( callback_test_null_config_ptr ) || ( callback_test_invalid_config ) ) { pass2 = FALSE; failure_mssg2 = "Bad parameter(s) to callback(7)."; } else if ( ( callback_test_null_data_ptr ) || ( callback_test_null_data_ptr_count != 0 ) ) { pass2 = FALSE; failure_mssg2 = "incorrect null data_ptr callbacks.(6)"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 17) Deregister the remaining callbacks, and then close and delete * the file. */ for ( i = max_callbacks - 1; i >= 0; i-- ) { if ( ( pass2 ) && ( ! free_entries[i] ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); while ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } HDassert( expected_num_entries == 0 ); HDassert( expected_max_idx == -1 ); HDassert( expected_table_len == H5C2__MIN_MDJSC_CB_TBL_LEN ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* Close the file, and tidy up. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fclose() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* delete the HDF5 file and journal file */ #if 1 HDremove(filename); HDremove(journal_filename); #endif if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d done.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } return; } /* verify_mdjsc_callback_execution() */ /*************************************************************************** * * Function: verify_mdjsc_callback_registration_deregistration() * * Purpose: Run a variety of tests to verify that the metadata * journaling status change callback registration and * deregistration works as expected. * * If all tests pass, do nothing. * * If anything is not as it should be, set pass2 to FALSE, * and set failure_mssg2 to the appropriate error message. * * Do nothing and return if pass2 is false on entry. * * Return: void * * Programmer: John Mainzer * 8/15/08 * **************************************************************************/ static void verify_mdjsc_callback_registration_deregistration(void) { const char * fcn_name = "verify_mdjsc_callback_registration_deregistration():"; char filename[512]; char journal_filename[H5AC2__MAX_JOURNAL_FILE_NAME_LEN + 1]; const int max_callbacks = 1024 * H5C2__MIN_MDJSC_CB_TBL_LEN; int counters[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; int i; int j; int expected_num_entries = 0; int expected_table_len = H5C2__MIN_MDJSC_CB_TBL_LEN; int expected_max_idx = -1; int32_t indicies[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; hbool_t free_entries[1024 * H5C2__MIN_MDJSC_CB_TBL_LEN]; hbool_t show_progress = FALSE; hbool_t verbose = FALSE; int cp = 0; hid_t file_id = -1; H5F_t * file_ptr = NULL; H5C2_t * cache_ptr = NULL; for ( i = 0; i < max_callbacks; i++ ) { counters[i] = 0; free_entries[i] = TRUE; indicies[i] = -1; } /* 1) Open a file for journaling. It doesn't matter whether * journaling is enabled or not, as this test is directed purely * at the issue of whether the callback table is managed correctly. * * 2) Register a callback. Verify that is is added correctly to * the metadata journaling status change callback table. * * 3) Deregister the callback. Verify that it is deleted correctly * from the metadata journaling status change callback table. * * 4) Register H5C2__MIN_MDJSC_CB_TBL_LEN - 1 callbacks. Verify that * they are all correctly added to the table, and that the table * is of size H5C2__MIN_MDJSC_CB_TBL_LEN, and that it contains * the expected number of entries. * * 5) Register one more entry. Verify that it is registered * correctly, and that the table is now full. * * 6) Register another entry. Verify that is is correctly registered, * that the table has doubled in size. * * 7) In LIFO order, deregister (H5C2__MIN_MDJSC_CB_TBL_LEN / 2) + 1 * callbacks in LIFO order. Verify that the entries are deregistered, * and that the table has not changed size. * * 8) Again, in LIFO order, deregister another callback. Verify that * the callback is deregistered, and that the table has been reduced * in size to H5C2__MIN_MDJSC_CB_TBL_LEN. * * 9) Deregister all callbacks. Verify that the table is empty. * * 10) Register 8 * H5C2__MIN_MDJSC_CB_TBL_LEN + 1 callbacks. Verify * that all callbacks are registered, and that the table lenght grows * to 16 * H5C2__MIN_MDJSC_CB_TBL_LEN. * * 11) Deregister all callbacks with even indicies. Verify the * deregistrations. Verify that the table does not shrink. * * 12) Register a callback. Verify that it is place in one of the * slots freed by the dergistrations in 11) above. * * 13) Starting with the lowest index, deregister all the callbacks. * Verify the deregistrations, and also verify that the table * does not shrink until the last callback is de-registered. * * 14) Register 8 * H5C2__MIN_MDJSC_CB_TBL_LEN + 1 callbacks. Verify * that all callbacks are registered, and that the table length grows * to 16 * H5C2__MIN_MDJSC_CB_TBL_LEN. * * 15) Starting with the highest index, deregister all entries with * index not divisible by H5C2__MIN_MDJSC_CB_TBL_LEN / 2. Verify * that the callbacks are de-registers, and that the table does * not shrink * * 16) Register H5C2__MIN_MDJSC_CB_TBL_LEN / 2 callbacks. Verify that * they are placed in slots freed by the dergistrations in 15) above. * * 17) Starting with the lowest index, deregister all entries with * index with index >= H5C2__MIN_MDJSC_CB_TBL_LEN and not divisible * by H5C2__MIN_MDJSC_CB_TBL_LEN. Verify that the callbacks are * deregistered, and that the table does not shrink. * * 18) Register a callback. Verify that it is place in one of the * slots freed by the dergistrations in 17) above. * * 19) Starting with the highest index, deregister all callbacks. * Verify that the table shrinks as expected. * * 20) Do a torture tests -- forcing the number of registered callbacks * into the thousands. After each registration and deregistration, * verify that the table is configured as expected. */ /* 1) Open a file for journaling. It doesn't matter whether * journaling is enabled or not, as this test is directed purely * at the issue of whether the callback table is managed correctly. */ /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (1).\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, pass2, cp++); HDfflush(stdout); } if ( verbose ) { HDfprintf(stdout, "%s filename = \"%s\".\n", fcn_name, filename); HDfflush(stdout); } /* setup the journal file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[3], H5P_DEFAULT, journal_filename, sizeof(journal_filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed (2).\n"; } else if ( strlen(journal_filename) >= H5AC2__MAX_JOURNAL_FILE_NAME_LEN ) { pass2 = FALSE; failure_mssg2 = "journal file name too long.\n"; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( verbose ) { HDfprintf(stdout, "%s journal filename = \"%s\".\n", fcn_name, journal_filename); HDfflush(stdout); } /* clean out any existing journal file */ HDremove(journal_filename); setup_cache_for_journaling(filename, journal_filename, &file_id, &file_ptr, &cache_ptr, FALSE); /* 2) Register a callback. Verify that is is added correctly to * the metadata journaling status change callback table. */ j = 0; register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[j]), &(indicies[j])); free_entries[j] = FALSE; expected_num_entries++; expected_max_idx = 0; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); j++; if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 3) Deregister the callback. Verify that it is deleted correctly * from the metadata journaling status change callback table. */ j--; deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[j]); free_entries[j] = TRUE; expected_num_entries--; expected_max_idx = -1; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 4) Register H5C2__MIN_MDJSC_CB_TBL_LEN - 1 callbacks. Verify that * they are all correctly added to the table, and that the table * is of size H5C2__MIN_MDJSC_CB_TBL_LEN, and that it contains * the expected number of entries. */ for ( i = 0; i < H5C2__MIN_MDJSC_CB_TBL_LEN - 1; i++ ) { register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[j]), &(indicies[j])); free_entries[j] = FALSE; expected_num_entries++; expected_max_idx++; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); j++; } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 5) Register one more entry. Verify that it is registered * correctly, and that the table is now full. */ register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[j]), &(indicies[j])); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } free_entries[j] = FALSE; expected_num_entries++; expected_max_idx++; if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); j++; if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } if ( ( pass2 ) && ( expected_num_entries != expected_table_len ) ) { pass2 = FALSE; failure_mssg2 = "Unexpected table len(1)"; } /* 6) Register another entry. Verify that is is correctly registered, * that the table has doubled in size. */ register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[j]), &(indicies[j])); free_entries[j] = FALSE; expected_num_entries++; expected_max_idx++; expected_table_len *= 2; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); j++; if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 7) In LIFO order, deregister (H5C2__MIN_MDJSC_CB_TBL_LEN / 2) + 1 * callbacks in LIFO order. Verify that the entries are deregistered, * and that the table has not changed size. */ for ( i = 0; i < (H5C2__MIN_MDJSC_CB_TBL_LEN / 2) + 1; i++ ) { j--; deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[j]); free_entries[j] = TRUE; expected_num_entries--; expected_max_idx--; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 8) Again, in LIFO order, deregister another callback. Verify that * the callback is deregistered, and that the table has been reduced * in size to H5C2__MIN_MDJSC_CB_TBL_LEN. */ j--; deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[j]); free_entries[j] = TRUE; expected_num_entries--; expected_max_idx--; expected_table_len /= 2; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 9) Deregister all callbacks. Verify that the table is empty. */ while ( expected_num_entries > 0 ) { j--; deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[j]); free_entries[j] = TRUE; expected_num_entries--; expected_max_idx--; verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 10) Register 8 * H5C2__MIN_MDJSC_CB_TBL_LEN + 1 callbacks. Verify * that all callbacks are registered, and that the table length grows * to 16 * H5C2__MIN_MDJSC_CB_TBL_LEN. */ for ( i = 0; i < ((8 * H5C2__MIN_MDJSC_CB_TBL_LEN) + 1); i++ ) { register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[i]), &(indicies[i])); HDassert( indicies[i] == i ); free_entries[i] = FALSE; expected_num_entries++; expected_max_idx++; if ( expected_num_entries > expected_table_len ) { expected_table_len *= 2; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } HDassert( expected_table_len == 16 * H5C2__MIN_MDJSC_CB_TBL_LEN ); HDassert( expected_table_len < 1024 ); HDassert( expected_max_idx == 8 * H5C2__MIN_MDJSC_CB_TBL_LEN ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 11) Deregister all callbacks with even indicies. Verify the * deregistrations. Verify that the table does not shrink. */ for ( i = 0; i < (8 * H5C2__MIN_MDJSC_CB_TBL_LEN) + 1; i += 2 ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { expected_max_idx--; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 12) Register a callback. Verify that it is place in one of the * slots freed by the dergistrations in 11) above. */ /* The index assigned to the new callback is determined by the * free list management algorithm. In the present implementation * freed entries are added to the head of the free list, so the * next index issues will be 8 * H5C2__MIN_MDJSC_CB_TBL_LEN. */ j = 8 * H5C2__MIN_MDJSC_CB_TBL_LEN; register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[j]), &(indicies[j])); HDassert( indicies[j] == j ); /* see comment above */ free_entries[j] = FALSE; expected_num_entries++; if ( j > expected_max_idx ) { expected_max_idx = j; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 13) Starting with the lowest index, deregister all the callbacks. * Verify the deregistrations, and also verify that the table * does not shrink until the last callback is de-registered. */ for ( i = 0; i < (8 * H5C2__MIN_MDJSC_CB_TBL_LEN) + 1; i++ ) { if ( ! free_entries[i] ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { expected_max_idx = -1; expected_table_len = H5C2__MIN_MDJSC_CB_TBL_LEN; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 14) Register 8 * H5C2__MIN_MDJSC_CB_TBL_LEN + 1 callbacks. Verify * that all callbacks are registered, and that the table length grows * to 16 * H5C2__MIN_MDJSC_CB_TBL_LEN. */ for ( i = 0; i < ((8 * H5C2__MIN_MDJSC_CB_TBL_LEN) + 1); i++ ) { register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[i]), &(indicies[i])); HDassert( indicies[i] == i ); free_entries[i] = FALSE; expected_num_entries++; expected_max_idx++; if ( expected_num_entries > expected_table_len ) { expected_table_len *= 2; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } HDassert( expected_table_len == 16 * H5C2__MIN_MDJSC_CB_TBL_LEN ); HDassert( expected_table_len < 1024 ); HDassert( expected_max_idx == 8 * H5C2__MIN_MDJSC_CB_TBL_LEN ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 15) Starting with the highest index, deregister all entries with * index not divisible by H5C2__MIN_MDJSC_CB_TBL_LEN / 2. Verify * that the callbacks are de-registers, and that the table does * not shrink */ for ( i = (8 * H5C2__MIN_MDJSC_CB_TBL_LEN); i >= 0; i-- ) { if ( ( ! free_entries[i] ) && ( (i % (H5C2__MIN_MDJSC_CB_TBL_LEN /2)) != 0 ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { expected_max_idx = -1; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 16) Register H5C2__MIN_MDJSC_CB_TBL_LEN / 2 callbacks. Verify that * they are placed in slots freed by the dergistrations in 15) above. */ /* The index assigned to the new callback is determined by the * free list management algorithm. In the present implementation * freed entries are added to the head of the free list, so the * next index issues will be 1. */ j = 1; for ( i = 0; i < H5C2__MIN_MDJSC_CB_TBL_LEN / 2; i++ ) { while ( ! free_entries[j] ) { j++; } register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[j]), &(indicies[j])); HDassert( indicies[j] == j ); /* see comment above */ free_entries[j] = FALSE; expected_num_entries++; if ( j > expected_max_idx ) { expected_max_idx = j; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } HDassert( j == (H5C2__MIN_MDJSC_CB_TBL_LEN / 2) + 1 ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 17) Starting with the lowest index, deregister all entries with * index with index >= H5C2__MIN_MDJSC_CB_TBL_LEN and not divisible * by H5C2__MIN_MDJSC_CB_TBL_LEN. Verify that the callbacks are * deregistered, and that the table does not shrink. */ for ( i = H5C2__MIN_MDJSC_CB_TBL_LEN; i < (8 * H5C2__MIN_MDJSC_CB_TBL_LEN) + 1; i++ ) { if ( ( ! free_entries[i] ) && ( (i % H5C2__MIN_MDJSC_CB_TBL_LEN) != 0 ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { expected_max_idx = -1; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 18) Register a callback. Verify that it is place in one of the * slots freed by the dergistrations in 17) above. */ /* The index assigned to the new callback is determined by the * free list management algorithm. In the present implementation * freed entries are added to the head of the free list, so the * next index issues will be (7 * H5C2__MIN_MDJSC_CB_TBL_LEN) + * (H5C2__MIN_MDJSC_CB_TBL_LEN / 2). */ j = (7 * H5C2__MIN_MDJSC_CB_TBL_LEN) + (H5C2__MIN_MDJSC_CB_TBL_LEN / 2); register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[j]), &(indicies[j])); HDassert( indicies[j] == j ); /* see comment above */ free_entries[j] = FALSE; expected_num_entries++; if ( j > expected_max_idx ) { expected_max_idx = j; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 19) Starting with the highest index, deregister all callbacks. * Verify that the table shrinks as expected. */ for ( i = (8 * H5C2__MIN_MDJSC_CB_TBL_LEN); i >= 0; i-- ) { if ( ( pass2 ) && ( ! free_entries[i] ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); if ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* 20) Do a torture tests -- forcing the number of registered callbacks * into the thousands. After each registration and deregistration, * verify that the table is configured as expected. */ /* register half the maximum number of callbacks in this test */ for ( i = 0; i < (max_callbacks / 2); i++ ) { register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[i]), &(indicies[i])); HDassert( indicies[i] == i ); free_entries[i] = FALSE; expected_num_entries++; expected_max_idx++; if ( expected_num_entries > expected_table_len ) { expected_table_len *= 2; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } HDassert( expected_table_len == (max_callbacks / 2) ); HDassert( expected_max_idx == ((max_callbacks / 2) - 1) ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* Starting from 3 * max_callbacks / 8 and working down to * max_callbacks / 8, deregister the odd index callbacks. */ for ( i = (3 * max_callbacks / 8); i >= max_callbacks / 8; i-- ) { if ( ( pass2 ) && ( ! free_entries[i] ) && ( (i % 2) == 1 ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); if ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* now re-register the callbacks just deregistered. To keep the test * at least somewhat sane, re-register the entries in the order they * appear in the free list, so as to maintain the indicies[i] == i * invarient. At present, this means re-registering entries the * the reverse of the order they were deregistered in. */ for ( i = (max_callbacks / 8); i <= (3 * max_callbacks / 8); i++ ) { if ( ( pass2 ) && ( free_entries[i] ) && ( (i % 2) == 1 ) ) { register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[i]), &(indicies[i])); HDassert( indicies[i] == i ); free_entries[i] = FALSE; expected_num_entries++; if ( i > expected_max_idx ) { expected_max_idx = i; } if ( expected_num_entries > expected_table_len ) { expected_table_len *= 2; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } HDassert( expected_num_entries == (max_callbacks / 2) ); HDassert( expected_max_idx == ((max_callbacks / 2) - 1) ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* now register more entries up to max_callbacks */ for ( i = (max_callbacks / 2); i < max_callbacks; i++ ) { if ( ( pass2 ) && ( free_entries[i] ) ) { register_mdjsc_callback(file_ptr, cache_ptr, test_mdjsc_callback, &(counters[i]), &(indicies[i])); HDassert( indicies[i] == i ); free_entries[i] = FALSE; expected_num_entries++; if ( i > expected_max_idx ) { expected_max_idx = i; } if ( expected_num_entries > expected_table_len ) { expected_table_len *= 2; } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } HDassert( expected_num_entries == max_callbacks ); HDassert( expected_max_idx == (max_callbacks - 1) ); HDassert( expected_table_len == max_callbacks ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* deregister every other 200 callbacks on increasing index */ for ( i = 0; i < max_callbacks; i += 200 ) { for ( j = i; ( ( i < j + 200 ) && ( j < max_callbacks ) ); j++ ) { if ( ( pass2 ) && ( ! free_entries[i] ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); if ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* working from the top downwards, de-register all entries with * indicies not divisible by 3. */ for ( i = max_callbacks - 1; i >= 0; i-- ) { if ( ( pass2 ) && ( ! free_entries[i] ) && ( (i % 3) != 0 ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); while ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* working from low index up, deregister all entries with index * greater than (max_callbacks / 8). */ for ( i = (max_callbacks / 8); i < max_callbacks; i++ ) { if ( ( pass2 ) && ( ! free_entries[i] ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); while ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } HDassert( expected_table_len == (max_callbacks / 8) ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* working from the top down, deregister the remaining callbacks. */ for ( i = (max_callbacks / 8); i >= 0; i-- ) { if ( ( pass2 ) && ( ! free_entries[i] ) ) { deregister_mdjsc_callback(file_ptr, cache_ptr, indicies[i]); indicies[i] = -1; free_entries[i] = TRUE; expected_num_entries--; if ( i == expected_max_idx ) { double fraction_in_use; while ( ( expected_max_idx >= 0 ) && ( free_entries[expected_max_idx] ) ) { expected_max_idx--; } fraction_in_use = ((double)expected_num_entries) / ((double)expected_table_len); while ( ( expected_max_idx < (expected_table_len / 2) ) && ( fraction_in_use < H5C2__MDJSC_CB_TBL_MIN_ACTIVE_RATIO ) && ( (expected_table_len / 2) >= H5C2__MIN_MDJSC_CB_TBL_LEN ) ) { expected_table_len /= 2; } } verify_mdjsc_table_config(cache_ptr, expected_table_len, expected_num_entries, expected_max_idx, free_entries); } } HDassert( expected_table_len == H5C2__MIN_MDJSC_CB_TBL_LEN ); HDassert( expected_num_entries == 0 ); HDassert( expected_max_idx == -1 ); if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* Close the file, and tidy up. */ if ( pass2 ) { if ( H5Fclose(file_id) < 0 ) { pass2 = FALSE; failure_mssg2 = "H5Fclose() failed."; } } if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } /* delete the HDF5 file and journal file */ #if 1 HDremove(filename); HDremove(journal_filename); #endif if ( show_progress ) { HDfprintf(stdout, "%s%d cp = %d done.\n", fcn_name, (int)pass2, cp++); HDfflush(stdout); } return; } /* verify_mdjsc_callback_registration_deregistration() */ /*************************************************************************** * Function: check_buffer_writes * * Purpose: Verify the function H5C_jb__write_to_buffer properly writes * messages of varying sizes into the journal buffers, and * that the journal buffers properly flush out when filled. * * Return: void * * Programmer: Mike McGreevy * Thursday, February 21, 2008 * **************************************************************************/ static void check_buffer_writes(void) { const char * fcn_name = "check_buffer_writes(): "; char filename[512]; int i; herr_t result; H5C2_jbrb_t jbrb_struct; FILE * readback; hbool_t show_progress = FALSE; int32_t checkpoint = 1; char filldata[12][100]; int repeatnum[12]; TESTING("metadata buffer & file writes"); pass2 = TRUE; /* Initialize data to get written as tests */ HDmemcpy(filldata[0], "abcdefghijklmn\n", 16); HDmemcpy(filldata[1], "ABCDEFGHIJKLMNO\n", 17); HDmemcpy(filldata[2], "AaBbCcDdEeFfGgHh\n", 18); HDmemcpy(filldata[3], "ZAB-ZAB-ZAB-ZAB-ZAB-ZAB-ZAB-ZA\n", 32); HDmemcpy(filldata[4], "ABC-ABC-ABC-ABC-ABC-ABC-ABC-ABC\n", 33); HDmemcpy(filldata[5], "BCD-BCD-BCD-BCD-BCD-BCD-BCD-BCD-\n", 34); HDmemcpy(filldata[6], "12345-12345-12345-12345-12345-12345-12345-1234\n", 48); HDmemcpy(filldata[7], "01234-01234-01234-01234-01234-01234-01234-01234\n", 49); HDmemcpy(filldata[8], "23456-23456-23456-23456-23456-23456-23456-23456-\n", 50); HDmemcpy(filldata[9], "aaaa-bbbb-cccc-dddd-eeee-ffff-gggg-hhhh-iiii-jjjj-kkkk-llll-mmmm-nnnn-oooo-pppp-qqqq-rrrr-ssss\n", 96); HDmemcpy(filldata[10], "bbbb-cccc-dddd-eeee-ffff-gggg-hhhh-iiii-jjjj-kkkk-llll-mmmm-nnnn-oooo-pppp-qqqq-rrrr-ssss-tttt-\n", 97); HDmemcpy(filldata[11], "cccc-dddd-eeee-ffff-gggg-hhhh-iiii-jjjj-kkkk-llll-mmmm-nnnn-oooo-pppp-qqqq-rrrr-ssss-tttt-uuuu-v\n", 98); /* Assert that size of data is as expected */ HDassert(HDstrlen(filldata[0]) == 15); HDassert(HDstrlen(filldata[1]) == 16); HDassert(HDstrlen(filldata[2]) == 17); HDassert(HDstrlen(filldata[3]) == 31); HDassert(HDstrlen(filldata[4]) == 32); HDassert(HDstrlen(filldata[5]) == 33); HDassert(HDstrlen(filldata[6]) == 47); HDassert(HDstrlen(filldata[7]) == 48); HDassert(HDstrlen(filldata[8]) == 49); HDassert(HDstrlen(filldata[9]) == 95); HDassert(HDstrlen(filldata[10]) == 96); HDassert(HDstrlen(filldata[11]) == 97); /* Give structure its magic number */ jbrb_struct.magic = H5C2__H5C2_JBRB_T_MAGIC; if ( show_progress ) /* 1 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 2 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, /* Buffer size */ 16, /* Number of Buffers */ 3, /* Use Synchronois I/O */ FALSE, /* human readable journal */ TRUE); if ( result != 0) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_init failed, check 1"; } /* end if */ } /* end if */ if ( show_progress ) /* 3 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush and truncate journal file to get rid of the header * message for subsequent tests. */ if ( pass2 ) { if ( H5C2_jb__flush(&jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_flush failed"; } /* end if */ } /* end if */ /* Truncate journal file */ if ( pass2 ) { if ( H5C2_jb__trunc(&jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_trunc failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 4 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* open journal file for reading */ readback = fopen(filename, "r"); /* run a collection of calls to write_flush_verify(). These calls * write specific lengths of data into the journal buffers and * then flushes them to disk, and ensures that what makes it to * disk is as expected */ for (i=0; i<12; i++) { write_flush_verify(&jbrb_struct, (int)HDstrlen(filldata[i]), filldata[i], readback); if ( show_progress ) HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); } /* end for */ /* run a collection of calls to write_noflush_verify(). These * calls write specific lengths of data into the journal buffers * multiple times, but only flushes at the end of the set of writes. * This tests to ensure that the automatic flush calls in * H5C2_jb__write_to_buffer are working properly. The routine then * ensures that what makes it it disk is as expected */ /* Initialize repeat array to specify how many times to repeat each write within the write_noflush_verify calls. */ repeatnum[0] = 16; repeatnum[1] = 6; repeatnum[2] = 16; repeatnum[3] = 16; repeatnum[4] = 6; repeatnum[5] = 16; repeatnum[6] = 16; repeatnum[7] = 6; repeatnum[8] = 16; repeatnum[9] = 16; repeatnum[10] = 6; repeatnum[11] = 16; for (i=0; i<12; i++) { write_noflush_verify(&jbrb_struct, (int)HDstrlen(filldata[i]), filldata[i], readback, repeatnum[i]); if ( show_progress ) HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); } /* end for */ /* close journal file pointer */ fclose(readback); /* Truncate the journal file */ if ( pass2 ) { if ( H5C2_jb__trunc(&jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ /* take down the journal file */ if ( pass2 ) { if (H5C2_jb__takedown(&jbrb_struct) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown failed"; } /* end if */ } /* end if */ /* report pass / failure information */ if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* check_buffer_writes */ /*************************************************************************** * Function: write_flush_verify * * Purpose: Helper function for check_buffer_writes test. Writes a * piece of data of specified size into the journal buffer, then * flushes the journal buffers. The data is read back and * verified for correctness. * * Return: void * * Programmer: Mike McGreevy * Thursday, February 21, 2008 * **************************************************************************/ static void write_flush_verify(H5C2_jbrb_t * struct_ptr, int size, char * data, FILE * readback) { char verify[150]; if ( pass2 ) { if ( H5C2_jb__write_to_buffer(struct_ptr, (size_t)size, data, 0, (uint64_t)0) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__write_to_buffer failed"; } /* end if */ } /* end if */ if ( pass2 ) { if ( H5C2_jb__flush(struct_ptr) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_flush failed"; } /* end if */ } /* end if */ if ( pass2 ) { fgets(verify, size+10, readback); if (HDstrcmp(verify, data) != 0) { pass2 = FALSE; failure_mssg2 = "Journal entry not written correctly"; } /* end if */ } /* end if */ return; } /* write_flush_verify */ /*************************************************************************** * Function: write_noflush_verify * * Purpose: Helper function for check_buffer_writes test. Writes a * piece of data of specified size into the journal buffer * multiple times, without calling H5C_jb__flush in between * writes. After all writes are completed, H5C_jb__flush is * called, and the data is read back from the journal file and * verified for correctness. * * Return: void * * Programmer: Mike McGreevy * Thursday, February 21, 2008 * **************************************************************************/ static void write_noflush_verify(H5C2_jbrb_t * struct_ptr, int size, char * data, FILE * readback, int repeats) { int i; char verify[150]; for (i=0; i * Tuesday, February 26, 2008 * **************************************************************************/ static void check_message_format(void) { const char * fcn_name = "check_message_format(): "; char filename[512]; int i; herr_t result; H5C2_jbrb_t jbrb_struct; FILE * readback; hbool_t show_progress = FALSE; int32_t checkpoint = 1; char verify[9][500]; char from_journal[9][500]; time_t current_date; TESTING("journal file message format"); pass2 = TRUE; /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed"; } /* end if */ } /* end if */ /* Give structure its magic number */ jbrb_struct.magic = H5C2__H5C2_JBRB_T_MAGIC; /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, /* Buffer size */ 16, /* Number of Buffers */ 3, /* Use Synchronois I/O */ FALSE, /* human readable journal */ TRUE); if ( result != 0) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_init failed, check 2"; } /* end if */ } /* end if */ if ( show_progress ) /* 1 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Start a transaction */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 2 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1, /* base address */ (haddr_t)0, /* data length */ 1, /* data */ (const uint8_t *)"A") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 3 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1, /* base address */ (haddr_t)1, /* data length */ 2, /* data */ (const uint8_t *)"AB") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 4 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1, /* base address */ (haddr_t)3, /* data length */ 4, /* data */ (const uint8_t *)"CDEF") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 5 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* End transaction */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 6 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Start a transaction */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 7 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)2, /* base address */ (haddr_t)285, /* data length */ 11, /* data */ (const uint8_t *)"Test Data?!") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 8 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* End transaction */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 9 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ current_date = time(NULL); if ( show_progress ) /* 10 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Fill out verify array with expected messages */ sprintf(verify[0], "0 ver_num 1 target_file_name HDF5.file creation_date %10.10s human_readable 1\n", ctime(¤t_date)); sprintf(verify[1], "1 bgn_trans 1\n"); sprintf(verify[2], "2 trans_num 1 length 1 base_addr 0x0 body 41 \n"); sprintf(verify[3], "2 trans_num 1 length 2 base_addr 0x1 body 41 42 \n"); sprintf(verify[4], "2 trans_num 1 length 4 base_addr 0x3 body 43 44 45 46 \n"); sprintf(verify[5], "3 end_trans 1\n"); sprintf(verify[6], "1 bgn_trans 2\n"); sprintf(verify[7], "2 trans_num 2 length 11 base_addr 0x11d body 54 65 73 74 20 44 61 74 61 3f 21 \n"); sprintf(verify[8], "3 end_trans 2\n"); /* verify that messages in journal are same as expected */ readback = fopen(filename, "r"); for (i = 0; i < 9; i++) { if ( pass2) { fgets(from_journal[i], 300, readback); if ( HDstrcmp(verify[i], from_journal[i]) != 0) { pass2 = FALSE; failure_mssg2 = "journal file not written correctly"; } /* end if */ } /* end if */ } /* end for */ fclose(readback); /* Truncate the journal file */ if ( pass2 ) { if ( H5C2_jb__trunc(&jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 11 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Start a transaction */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)3) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 12 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)3, /* base address */ (haddr_t)28591, /* data length */ 6, /* data */ (const uint8_t *)"#1nN`}") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 13 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* End transaction */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* trans number */ (uint64_t)3) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 14 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Add a comment */ if ( pass2 ) { if ( H5C2_jb__comment(/* H5C2_jbrb_t */ &jbrb_struct, /* comment message */ "This is a comment!") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__comment failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 14 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Add a comment */ if ( pass2 ) { if ( H5C2_jb__comment(/* H5C2_jbrb_t */ &jbrb_struct, /* comment message */ "This is another comment!") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__comment failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 14 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ current_date = time(NULL); if ( show_progress ) /* 15 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Fill out verify array with expected messages */ sprintf(verify[0], "0 ver_num 1 target_file_name HDF5.file creation_date %10.10s human_readable 1\n", ctime(¤t_date)); sprintf(verify[1], "1 bgn_trans 3\n"); sprintf(verify[2], "2 trans_num 3 length 6 base_addr 0x6faf body 23 31 6e 4e 60 7d \n"); sprintf(verify[3], "3 end_trans 3\n"); sprintf(verify[4], "C comment This is a comment!\n"); sprintf(verify[5], "C comment This is another comment!\n"); /* verify that messages in journal are same as expected */ readback = fopen(filename, "r"); for (i = 0; i < 6; i++) { if ( pass2) { fgets(from_journal[i], 300, readback); if ( HDstrcmp(verify[i], from_journal[i]) != 0) { pass2 = FALSE; failure_mssg2 = "journal file not written correctly"; } /* end if */ } /* end if */ } /* end for */ fclose(readback); /* Truncate the journal file */ if ( pass2 ) { if ( H5C2_jb__trunc(&jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ /* take down the journal file */ if ( pass2 ) { if (H5C2_jb__takedown(&jbrb_struct) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 16 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* report pass / failure information */ if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* end check_message_format */ /*************************************************************************** * Function: check_legal_calls * * Purpose: Verify that all H5C_jb functions prevent use when appropriate. * * Return: void * * Programmer: Mike McGreevy * Tuesday, February 26, 2008 * **************************************************************************/ static void check_legal_calls(void) { const char * fcn_name = "check_legal_calls(): "; char filename[512]; herr_t result; H5C2_jbrb_t jbrb_struct; hbool_t show_progress = FALSE; int32_t checkpoint = 1; TESTING("journaling routine compatibility"); pass2 = TRUE; /* Give structure its magic number */ jbrb_struct.magic = H5C2__H5C2_JBRB_T_MAGIC; /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 1 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Initialize H5C2_jbrb_t structure. This call should SUCCEED. */ if ( pass2 ) { result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, /* Buffer size */ 4000, /* Number of Buffers */ 3, /* Use Synchronois I/O */ FALSE, /* human readable journal */ TRUE); if ( result != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_init failed, check 3"; } /* end if */ } /* end if */ if ( show_progress ) /* 2 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); #if 0 /* Start transaction 2. This should FAIL because transaction 1 has not occurred yet. Ensure that it fails, and flag an error if it does not. */ /* transaction numbers need not be sequential, only monitonically * increasing -- thus this is not an error any more. * -- JRM */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2) == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction should have failed"; } /* end if */ } /* end if */ #endif if ( show_progress ) /* 3 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* End transaction 1. This should FAIL because transaction 1 has not started yet. Ensure that it fails, and flag an error if it does not. */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 4 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to write a journal entry before transaction has started.. This should FAIL because transaction 1 has not started yet. Ensure that it fails, and flag an error if it does not. */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 16, /* Body */ (const uint8_t *)"This should fail") == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 5 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Start transaction 1. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 6 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to start transaction 1 again. This should FAIL because transaction 1 is already open. Ensure that it fails, and flag an error if it does not. */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 7 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to end transaction 1. This should FAIL because no journal entry has been written under this transaction. */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 8 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to write a journal entry into the wrong transaction number. This should FAIL because specified transaction number isn't in progress. Ensure that it fails, and flag an error if it does not. */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2, /* Base Address */ (haddr_t)123456789, /* Length */ 16, /* Body */ (const uint8_t *)"This should fail") == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 9 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry during transaction 1. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1, /* Base Address */ (haddr_t)123456789, /* Length */ 51, /* Body */ (const uint8_t *)"This is the first transaction during transaction 1.") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 10 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to flush buffers. This should FAIL because a transaction is still in progress. Ensure that it fails, and flag an error if it does not. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 11 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* End transaction 1. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 12 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to start transaction 1 again. This should FAIL because transaction 1 has already occurred. Ensure that it fails, and flag an error if it does not. */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)1) == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 13 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Start transaction 2. This should SUCCEED.*/ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 14 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry during transaction 2. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2, /* Base Address */ (haddr_t)7465, /* Length */ 51, /* Body */ (const uint8_t *)"This is the first transaction during transaction 2!") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 15 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write a journal entry during transaction 2. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2, /* Base Address */ (haddr_t)123456789, /* Length */ 60, /* Body */ (const uint8_t *)"... And here's your second transaction during transaction 2.") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 16 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* End transaction 2. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ &jbrb_struct, /* Transaction # */ (uint64_t)2) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 17 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to truncate the journal file. This should FAIL because the journal buffers have not been flushed yet. Ensure that it fails, and flag and error if it does not. */ if ( pass2 ) { if ( H5C2_jb__trunc(/* H5C2_jbrb_t */ &jbrb_struct) == SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 18 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to take down the ring buffer. This should FAIL because the journal buffers have not been flushed yet. Ensure that it fails, and flag and error if it does not. */ if ( pass2 ) { if (H5C2_jb__takedown(/* H5C2_jbrb_t */ &jbrb_struct) == SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 19 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 20 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Attempt to take down the ring buffer. This should FAIL because the journal file has not been truncated. Ensure that it fails, and flag and error if it does not. */ if ( pass2 ) { if (H5C2_jb__takedown(/* H5C2_jbrb_t */ &jbrb_struct) == SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown should have failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 21 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Truncate the journal file. This should SUCCEED. */ if ( pass2 ) { if ( H5C2_jb__trunc(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 22 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Take down the journal file. This should SUCCEED. */ if ( pass2 ) { if (H5C2_jb__takedown(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 23 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* report pass / failure information */ if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* end check_legal_calls */ /*************************************************************************** * Function: check_transaction_tracking * * Purpose: Verify that the ring buffer successfully tracks when * transactions make it to disk. * * Return: void * * Programmer: Mike McGreevy * Tuesday, February 26, 2008 * **************************************************************************/ static void check_transaction_tracking(void) { const char * fcn_name = "check_transaction_tracking(): "; char filename[512]; int i; herr_t result; H5C2_jbrb_t jbrb_struct; hbool_t show_progress = FALSE; int32_t checkpoint = 1; int expected_tval[12]; TESTING("journal file transaction tracking"); pass2 = TRUE; /* setup the file name */ if ( pass2 ) { if ( h5_fixname(FILENAMES[1], H5P_DEFAULT, filename, sizeof(filename)) == NULL ) { pass2 = FALSE; failure_mssg2 = "h5_fixname() failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 1 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Give structure its magic number */ jbrb_struct.magic = H5C2__H5C2_JBRB_T_MAGIC; /* =================================================== * First ring buffer configuration. * 4 Buffers, each size 250. * Writing transactions of size 100. * Test cases: * - writing multiple transactions in each buffer * - writing end transaction message to exact end * of a journal buffer, as well as the exact end * of the ring buffer. * =================================================== */ /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, /* Buffer size */ 250, /* Number of Buffers */ 4, /* Use Synchronois I/O */ FALSE, /* human readable journal */ TRUE); if ( result != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_init failed, check 4"; } /* end if */ } /* end if */ if ( show_progress ) /* 2 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 3 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write journal entries and verify that the transactions that get to disk are accurately reported after each write. The following test the case where multiple journal entries reside in each buffer before a flush occurs. Also, the case when a transaction ends on a buffer boundary is also tested. */ /* set up array of expected transaction values on disk */ expected_tval[1] = 0; expected_tval[2] = 0; expected_tval[3] = 2; expected_tval[4] = 2; expected_tval[5] = 5; expected_tval[6] = 5; expected_tval[7] = 5; expected_tval[8] = 7; expected_tval[9] = 7; expected_tval[10] = 10; /* write 20 messages and verify that expected values are as indicated in the expected_tval array */ for (i = 1; i < 11; i++) { write_verify_trans_num(/* H5C2_jbrb_t */ &jbrb_struct, /* transaction num */ (uint64_t)i, /* expected trans */(uint64_t)expected_tval[i]); } /* end for */ if ( show_progress ) /* 4 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ /* Truncate the journal file. */ if ( pass2 ) { if ( H5C2_jb__trunc(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ /* Take down the journal file. */ if ( pass2 ) { if (H5C2_jb__takedown(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 5 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* =================================================== * Second ring buffer configuration * 4 Buffers, each size 100. * Writing transactions of size 100. * Test cases: * - end transaction messages appear on buffer * boundaries. * =================================================== */ /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, /* Buffer size */ 100, /* Number of Buffers */ 4, /* Use Synchronois I/O */ FALSE, /* human readable journal */ TRUE); if ( result != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_init failed, check 5"; } /* end if */ } /* end if */ /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 6 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write journal entries and verify that the transactions that get to disk are accurately reported after each write. The following tests the case where end transaction messages hit exactly at the end of the ring buffer. */ for (i=1; i<20; i++) { write_verify_trans_num(/* H5C2_ujbrb_t */&jbrb_struct, /* transaction num */(uint64_t)i, /* expected trans on disk */(uint64_t)i); } /* end for */ if ( show_progress ) /* 7 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ /* Truncate the journal file. */ if ( pass2 ) { if ( H5C2_jb__trunc(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ /* Take down the journal file. */ if ( pass2 ) { if (H5C2_jb__takedown(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown failed"; } /* end if */ } /* end if */ /* =================================================== * Third ring buffer configuration * 10 Buffers, each size 30. * Writing transactions of size 100. * Test cases: * - end transaction messages start in one buffer * and end in the following buffer. * - end transaction messages start in the last * buffer and loop around to the first buffer. * - multiple buffers are filled between end * transaction messages. * =================================================== */ /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, /* Buffer size */ 30, /* Number of Buffers */ 10, /* Use Synchronois I/O */ FALSE, /* human readable journal */ TRUE); if ( result != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_init failed, check 6"; } /* end if */ } /* end if */ if ( show_progress ) /* 8 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 9 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write journal entries and verify that the transactions that get to disk are accurately reported after each write. The following tests the case where end transaction messages start in one buffer and end in another buffer. Also tests the case where one transaction ends several buffers ahead of the next transaction end. */ write_verify_trans_num(&jbrb_struct, (uint64_t)1, (uint64_t)0); /* 1 in bufs, 0 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)2, (uint64_t)1); /* 2 in bufs, 1 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)3, (uint64_t)3); /* nothing in bufs, 3 on disk */ H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, (uint64_t)0); write_verify_trans_num(&jbrb_struct, (uint64_t)4, (uint64_t)3); /* 1 in bufs, 0 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)5, (uint64_t)5); /* 2 in bufs, 1 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)6, (uint64_t)5); /* nothing in bufs, 3 on disk */ H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, (uint64_t)0); write_verify_trans_num(&jbrb_struct, (uint64_t)7, (uint64_t)7); /* 1 in bufs, 0 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)8, (uint64_t)7); /* 2 in bufs, 1 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)9, (uint64_t)8); /* nothing in bufs, 3 on disk */ H5C2_jb__write_to_buffer(&jbrb_struct, 10, "XXXXXXXXX\n", 0, (uint64_t)0); write_verify_trans_num(&jbrb_struct, (uint64_t)10, (uint64_t)9); /* 1 in bufs, 0 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)11, (uint64_t)10); /* 2 in bufs, 1 on disk */ write_verify_trans_num(&jbrb_struct, (uint64_t)12, (uint64_t)12); /* nothing in buf, 3 on disk */ if ( show_progress ) /* 10 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ /* Truncate the journal file. */ if ( pass2 ) { if ( H5C2_jb__trunc(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ /* Take down the journal file. */ if ( pass2 ) { if (H5C2_jb__takedown(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown failed"; } /* end if */ } /* end if */ /* =================================================== * Fourth ring buffer configuration * 35 Buffers, each size 1. * Writing transactions of size 100. * Test cases: * - end transaction messages are longer than the * entire ring buffer structure. note this is an * extreme corner case situation as buffer sizes * should generally be much larger than an end * transaction message. * =================================================== */ /* Initialize H5C2_jbrb_t structure. */ if ( pass2 ) { result = H5C2_jb__init(/* H5C2_jbrb_t */ &jbrb_struct, /* HDF5 file name */ HDF5_FILE_NAME, /* journal file name */ filename, /* Buffer size */ 1, /* Number of Buffers */ 35, /* Use Synchronois I/O */ FALSE, /* human readable journal */ TRUE); if ( result != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb_init failed, check 7"; } /* end if */ } /* end if */ /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 11 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Write journal entries and verify that the transactions that get to disk are accurately reported after each write. The following tests the case where end transaction messages take up several journal buffers, and ensures that the trans_tracking array is properly propogated */ for (i=1; i<5; i++) { write_verify_trans_num(/* H5C2_jbrb_t */ &jbrb_struct, /* transaction num */ (uint64_t)i, /* expected returned trans */ (uint64_t)i); } /* end for */ if ( show_progress ) /* 12 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* Flush the journal buffers. */ if ( pass2 ) { if ( H5C2_jb__flush(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__flush failed"; } /* end if */ } /* end if */ /* Truncate the journal file. */ if ( pass2 ) { if ( H5C2_jb__trunc(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__trunc failed"; } /* end if */ } /* end if */ /* Take down the journal file. */ if ( pass2 ) { if (H5C2_jb__takedown(/* H5C2_jbrb_t */ &jbrb_struct) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__takedown failed"; } /* end if */ } /* end if */ if ( show_progress ) /* 13 */ HDfprintf(stdout, "%s%0d -- pass = %d\n", fcn_name, checkpoint++, (int)pass2); /* report pass / failure information */ if ( pass2 ) { PASSED(); } else { H5_FAILED(); } if ( ! pass2 ) { failures2++; HDfprintf(stdout, "%s: failure_mssg2 = \"%s\".\n", fcn_name, failure_mssg2); } return; } /* end check_transaction_tracking */ /*************************************************************************** * Function: write_verify_trans_num * * Purpose: Helper function for check_transaction_tracking test. Writes a * journal entry of length 100 into the ring buffer, provided that * the transaction number of the journal entry is less than 1000, * and then verifies that the recorded last transaction on disk is * as specified in verify_val. * * Return: void * * Programmer: Mike McGreevy * Thursday, February 28, 2008 * **************************************************************************/ static void write_verify_trans_num(H5C2_jbrb_t * struct_ptr, uint64_t trans_num, uint64_t verify_val) { uint64_t trans_verify; /* Write an entire transaction. (start, journal entry, end). * As long as the supplied transaction number is less than 1000, * the total length of the transaction will be 100. For cases where * the transaction number increases in number of digits, the amount * of data in the body is reduced to account for the extra trans digits, * so transactions remain at size 100. Note that data is converted * into hex, so reducing input by one character reduces journal entry * by three (two hex characters and a space). */ if ( pass2 ) { if ( H5C2_jb__start_transaction(/* H5C2_jbrb_t */ struct_ptr, /* trans number */ trans_num) != SUCCEED) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__start_transaction failed"; } /* end if */ if (trans_num < 10) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ struct_ptr, /* Transaction # */ trans_num, /* Base Address */ (haddr_t)16, /* Length */ 9, /* Body */ (const uint8_t *)"XXXXXXXXX") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end if */ else if (trans_num < 100) { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ struct_ptr, /* Transaction # */ trans_num, /* Base Address */ (haddr_t)16, /* Length */ 8, /* Body */ (const uint8_t *)"XXXXXXXX") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end else if */ else { if ( H5C2_jb__journal_entry(/* H5C2_jbrb_t */ struct_ptr, /* Transaction # */ trans_num, /* Base Address */ (haddr_t)16, /* Length */ 7, /* Body */ (const uint8_t *)"XXXXXXX") != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__journal_entry failed"; } /* end if */ } /* end else */ if ( H5C2_jb__end_transaction(/* H5C2_jbrb_t */ struct_ptr, /* Transaction # */ trans_num) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__end_transaction failed"; } /* end if */ } /* end if */ /* Make sure the last transaction that's on disk is as expected. */ if ( pass2 ) { if ( H5C2_jb__get_last_transaction_on_disk( /* H5C2_jbrb_t */ struct_ptr, /* trans number */ &trans_verify) != SUCCEED ) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__get_last_transaction_on_disk failed"; } /* end if */ if ( trans_verify != verify_val) { pass2 = FALSE; failure_mssg2 = "H5C2_jb__get_last_transaction_on_disk returned the wrong transaction number!"; } /* end if */ } /* end if */ return; } /* end write_verify_trans_num */ /*------------------------------------------------------------------------- * Function: main * * Purpose: Run tests on the cache code contained in H5C2.c * * Return: Success: * * Failure: * * Programmer: John Mainzer * 6/24/04 * * Modifications: * *------------------------------------------------------------------------- */ int main(void) { int express_test; failures2 = 0; H5open(); express_test = GetTestExpress(); if ( express_test2 >= 3 ) { skip_long_tests2 = TRUE; } else { skip_long_tests2 = FALSE; } #if 1 mdj_smoke_check_00(); #endif #if 1 mdj_smoke_check_01(); #endif #if 1 mdj_smoke_check_02(); #endif #if 1 mdj_api_example_test(); #endif #if 1 check_buffer_writes(); check_legal_calls(); check_message_format(); check_transaction_tracking(); #endif #if 1 check_superblock_extensions(); #endif #if 1 check_mdj_config_block_IO(); #endif #if 1 check_mdjsc_callbacks(); #endif return(failures2); } /* main() */