QIO_ChecksumInfo *QIO_read_checksum(QIO_Reader *in) { char myname[] = "QIO_read_checksum"; QIO_String *xml_checksum; QIO_ChecksumInfo *checksum_info_expect = NULL; int this_node = in->layout->this_node; int status; LIME_type lime_type=NULL; if(in->read_state != QIO_RECORD_CHECKSUM_NEXT){ printf("%s(%d): Bad read state %d\n",myname,this_node,in->read_state); return NULL; } /* Master node reads the checksum record */ status = QIO_SUCCESS; /* Changed if checksum does not match */ if(this_node == in->layout->master_io_node){ checksum_info_expect = QIO_create_checksum_info(0,0); /* No checksum record for non-native files */ if(in->format == QIO_SCIDAC_NATIVE){ xml_checksum = QIO_string_create(); QIO_string_realloc(xml_checksum,QIO_STRINGALLOC); if((status=QIO_read_string(in, xml_checksum, &lime_type)) !=QIO_SUCCESS){ printf("%s(%d): Error reading checksum\n",myname,this_node); return NULL; } if(QIO_verbosity() >= QIO_VERB_DEBUG){ printf("%s(%d): checksum = %s\n",myname,this_node, QIO_string_ptr(xml_checksum)); } /* Extract checksum */ if((status=QIO_decode_checksum_info(checksum_info_expect, xml_checksum)) !=0){ printf("%s(%d): bad checksum record\n",myname,this_node); return NULL; } QIO_string_destroy(xml_checksum); } } in->read_state = QIO_RECORD_INFO_PRIVATE_NEXT; return checksum_info_expect; }
int QIO_compare_checksum_info(QIO_ChecksumInfo *found, QIO_ChecksumInfo *expect, char *myname, int this_node){ if(!QIO_defined_suma(found) || !QIO_defined_sumb(found)){ printf("%s(%d): checksum info missing\n",myname,this_node); return QIO_ERR_CHECKSUM_INFO; } if(QIO_get_suma(expect) != QIO_get_suma(found) || QIO_get_sumb(expect) != QIO_get_sumb(found)){ printf("%s(%d): Checksum mismatch. Found %x %x. Expected %x %x\n", myname,this_node,QIO_get_suma(found),QIO_get_sumb(found), QIO_get_suma(expect),QIO_get_sumb(expect) ); return QIO_CHECKSUM_MISMATCH; } else if(QIO_verbosity() >= QIO_VERB_DEBUG) printf("%s(%d): Checksums %x %x OK\n",myname,this_node, QIO_get_suma(found),QIO_get_sumb(found)); return QIO_SUCCESS; }
int QIO_generic_read_record_data(QIO_Reader *in, void (*put)(char *buf, size_t index, int count, void *arg), size_t datum_size, int word_size, void *arg, DML_Checksum *checksum, uint64_t *nbytes) { char myname[] = "QIO_generic_read_record_data"; int count; LRL_RecordReader *lrl_record_in; size_t datum_size_info; DML_Layout *layout = in->layout; int this_node = layout->this_node; int status; int recordtype; int latdim; QIO_RecordInfo *record_info = &in->record_info; /* List of acceptable binary data LIME types */ int ntypes = 2; /* Avoid a compiler bug */ LIME_type lime_type0 = QIO_LIMETYPE_BINARY_DATA; LIME_type lime_type1 = QIO_LIMETYPE_ILDG_BINARY_DATA; LIME_type lime_type_list[2] = {lime_type0, lime_type1}; // LIME_type lime_type_list[2] = { // QIO_LIMETYPE_BINARY_DATA, // QIO_LIMETYPE_ILDG_BINARY_DATA // }; LIME_type lime_type; /* It is an error to call for the data before reading the info in a given record */ if(in->read_state != QIO_RECORD_DATA_NEXT){ printf("%s(%d): Bad read state %d\n",myname,this_node,in->read_state); return QIO_ERR_INFO_MISSED; } /* Add record type and subset data to layout structure */ recordtype = QIO_get_recordtype(record_info); layout->recordtype = recordtype; status = DML_insert_subset_data(layout, QIO_get_hyperlower(record_info), QIO_get_hyperupper(record_info), QIO_get_hyper_spacetime(record_info)); if(status != 0) return QIO_ERR_BAD_SUBSET; /* Require consistency between the byte count obtained from the private record metadata and the datum_size and count parameters (per site for field or hypercube data or total for global data) */ count = QIO_get_datacount(record_info); if(datum_size != QIO_get_typesize(record_info) * count) { printf("%s(%d): requested byte count %lu disagrees with the record %d * %d\n", myname,this_node,(unsigned long)datum_size, QIO_get_typesize(record_info), count); if(this_node == layout->master_io_node) QIO_print_record_info(record_info); return QIO_ERR_BAD_READ_BYTES; } /* Verify byte count per site (for field or hypercube) or total (for global) */ datum_size_info = QIO_get_typesize(record_info) * count; if(datum_size != datum_size_info){ printf("%s(%d): byte count mismatch request %lu != actual %lu\n", myname, this_node, (unsigned long)datum_size, (unsigned long)datum_size_info); return QIO_ERR_BAD_READ_BYTES; } if(QIO_verbosity() >= QIO_VERB_DEBUG){ printf("%s(%d): Calling QIO_open_read_field\n",myname,this_node);fflush(stdout); } /* Nodes read the field */ /* Scan ahead and open the record with one of the listed LIME types */ lrl_record_in = QIO_open_read_field(in, recordtype, datum_size, lime_type_list, ntypes, &lime_type, &status); if(status != QIO_SUCCESS)return status; if(QIO_verbosity() >= QIO_VERB_DEBUG){ printf("%s(%d): Calling QIO_read_field_data\n", myname,this_node);fflush(stdout); } /* Then read the data and close the record */ status = QIO_read_field_data(in, lrl_record_in, recordtype, put, count, datum_size, word_size, arg, checksum, nbytes); if(status != QIO_SUCCESS){ printf("%s(%d): Error reading field data\n",myname,this_node); return status; } if(QIO_verbosity() >= QIO_VERB_DEBUG){ printf("%s(%d): done reading field\n",myname,this_node);fflush(stdout); } /* Copy most recent node checksum into reader */ memcpy(&(in->last_checksum), checksum, sizeof(DML_Checksum)); if(this_node == layout->master_io_node){ if(QIO_verbosity() >= QIO_VERB_REG){ printf("%s(%d): Read field\n",myname,this_node); QIO_print_record_info(record_info); } } in->read_state = QIO_RECORD_CHECKSUM_NEXT; return QIO_SUCCESS; }
int QIO_read_record_data(QIO_Reader *in, void (*put)(char *buf, size_t index, int count, void *arg), size_t datum_size, int word_size, void *arg){ char myname[] = "QIO_read_record_data"; DML_Checksum checksum; uint64_t nbytes, expect_bytes; QIO_ChecksumInfo *checksum_info_expect; size_t buf_size; size_t volume; int this_node = in->layout->this_node; int status; int recordtype = QIO_get_recordtype(&(in->record_info)); if(QIO_verbosity() >= QIO_VERB_DEBUG){ printf("%s(%d): Calling QIO_generic_read_record_data\n", myname,this_node);fflush(stdout); } status = QIO_generic_read_record_data(in, put, datum_size, word_size, arg, &checksum, &nbytes); if(status != QIO_SUCCESS)return status; /* Total number of sites in this record */ volume = in->layout->subsetvolume; /* Compute the number of bytes read by all nodes */ DML_sum_uint64_t(&nbytes); /* Check that the record size matches the expected size of the data */ if(recordtype == QIO_GLOBAL){ buf_size = datum_size; /* Global data */ expect_bytes = buf_size; } else { /* Field data */ expect_bytes = ((uint64_t)volume) * datum_size; } if(nbytes != expect_bytes){ printf("%s(%d): bytes read %lu != expected rec_size %lu\n", myname, in->layout->this_node, (unsigned long)nbytes, (unsigned long)expect_bytes); return QIO_ERR_BAD_READ_BYTES; } /* Combine checksums over all nodes */ DML_checksum_combine(&checksum); /* Copy most recent combined checksum into reader */ memcpy(&(in->last_checksum), &checksum, sizeof(DML_Checksum)); /* Everyone calls this. It changes the state machine */ checksum_info_expect = QIO_read_checksum(in); if(this_node == in->layout->master_io_node) { if(in->format == QIO_SCIDAC_NATIVE){ if(checksum_info_expect == NULL)return QIO_ERR_CHECKSUM_INFO; status = QIO_compare_checksum(this_node, checksum_info_expect, &checksum); if(status != QIO_SUCCESS)return status; } } /* Checksum info expect may be NULL on non master node. This is not an error. Freeing it is */ if( checksum_info_expect != NULL ) { QIO_destroy_checksum_info(checksum_info_expect); } if(QIO_verbosity() >= QIO_VERB_DEBUG){ printf("%s(%d): done with QIO_read_record_data\n", myname,in->layout->this_node);fflush(stdout); } return QIO_SUCCESS; }