/** Apply the transform to a buffer starting at "data". That buffer MUST be ROZOFS_BSIZE aligned. The first_block_idx is the index of a ROZOFS_BSIZE array in the output buffer The number_of_blocks is the number of ROZOFS_BSIZE that must be transform Notice that the first_block_idx offset applies to the output transform buffer only not to the input buffer pointed by "data". * * @param *working_ctx_p: storcli working context * @param number_of_blocks: number of blocks to write * @param *data: pointer to the source data that must be transformed * * @return: the length written on success, -1 otherwise (errno is set) */ void rozofs_storcli_transform_forward_repair(rozofs_storcli_ctx_t *working_ctx_p, uint8_t layout, uint32_t number_of_blocks, char *data) { projection_t rozofs_fwd_projections[ROZOFS_SAFE_MAX_STORCLI]; projection_t *projections; // Table of projections used to transform data uint16_t projection_id = 0; uint32_t i = 0; uint8_t rozofs_forward = rozofs_get_rozofs_forward(layout); uint8_t rozofs_safe = rozofs_get_rozofs_forward(layout); uint8_t rozofs_inverse = rozofs_get_rozofs_inverse(layout); rozofs_storcli_projection_ctx_t *prj_ctx_p = &working_ctx_p->prj_ctx[0]; int empty_block = 0; uint8_t sid; int moj_prj_id; int block_idx; int k; storcli_read_arg_t *storcli_read_rq_p = (storcli_read_arg_t*)&working_ctx_p->storcli_read_arg; uint8_t bsize = storcli_read_rq_p->bsize; uint32_t bbytes = ROZOFS_BSIZE_BYTES(bsize); int prj_size_in_msg = rozofs_get_max_psize_in_msg(layout,bsize); projections = rozofs_fwd_projections; // For each projection for (projection_id = 0; projection_id < rozofs_forward; projection_id++) { projections[projection_id].angle.p = rozofs_get_angles_p(layout,projection_id); projections[projection_id].angle.q = rozofs_get_angles_q(layout,projection_id); projections[projection_id].size = rozofs_get_128bits_psizes(layout,bsize,projection_id); } /* ** now go through all projection set to find out if there is something to regenerate */ for (k = 0; k < rozofs_safe; k++) { block_idx = 0; if (ROZOFS_BITMAP64_TEST_ALL0(prj_ctx_p[k].crc_err_bitmap)) continue; /* ** Get the sid associated with the projection context */ sid = (uint8_t) rozofs_storcli_lbg_prj_get_sid(working_ctx_p->lbg_assoc_tb, prj_ctx_p[k].stor_idx); /* ** Get the reference of the Mojette projection_id */ moj_prj_id = rozofs_storcli_get_mojette_proj_id(storcli_read_rq_p->dist_set,sid,rozofs_forward); if (moj_prj_id < 0) { /* ** it is the reference of a spare sid, so go to the next projection context */ continue; } for (i = 0; i < number_of_blocks; i++) { if (ROZOFS_BITMAP64_TEST0(i,prj_ctx_p[k].crc_err_bitmap)) { /* ** nothing to generate for that block */ continue; } /* ** check for empty block */ empty_block = rozofs_data_block_check_empty(data + (i * bbytes), bbytes); /** * regenerate the projection for the block for which a crc error has been detected */ //CRC projections[moj_prj_id].bins = prj_ctx_p[moj_prj_id].bins + projections[moj_prj_id].bins = prj_ctx_p[k].bins + (prj_size_in_msg/sizeof(bin_t)* (0+block_idx)); rozofs_stor_bins_hdr_t *rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t*)projections[moj_prj_id].bins; /* ** check if the user data block is empty: if the data block is empty no need to transform */ if (empty_block) { rozofs_bins_hdr_p->s.projection_id = 0; rozofs_bins_hdr_p->s.timestamp = 0; rozofs_bins_hdr_p->s.effective_length = 0; rozofs_bins_hdr_p->s.filler = 0; rozofs_bins_hdr_p->s.version = 0; block_idx++; continue; } /* ** fill the header of the projection */ rozofs_bins_hdr_p->s.projection_id = moj_prj_id; //CRC rozofs_bins_hdr_p->s.timestamp = working_ctx_p->block_ctx_table[block_idx].timestamp; rozofs_bins_hdr_p->s.timestamp = working_ctx_p->block_ctx_table[i].timestamp; //CRC rozofs_bins_hdr_p->s.effective_length = working_ctx_p->block_ctx_table[block_idx].effective_length; rozofs_bins_hdr_p->s.effective_length = working_ctx_p->block_ctx_table[i].effective_length; rozofs_bins_hdr_p->s.filler = 0; rozofs_bins_hdr_p->s.version = 0; /* ** update the pointer to point out the first bins */ projections[moj_prj_id].bins += sizeof(rozofs_stor_bins_hdr_t)/sizeof(bin_t); /* ** do not apply transform for empty block */ if (empty_block == 0) { /* ** Apply the erasure code transform for the block i */ transform128_forward_one_proj((pxl_t *) (data + (i * bbytes)), rozofs_inverse, bbytes / rozofs_inverse / sizeof (pxl_t), moj_prj_id, projections); /* ** add the footer at the end of the repaired projection */ rozofs_stor_bins_footer_t *rozofs_bins_foot_p; rozofs_bins_foot_p = (rozofs_stor_bins_footer_t*) (projections[moj_prj_id].bins + rozofs_get_psizes(layout,bsize,moj_prj_id)); //CRC rozofs_bins_foot_p->timestamp = working_ctx_p->block_ctx_table[block_idx].timestamp; rozofs_bins_foot_p->timestamp = rozofs_bins_hdr_p->s.timestamp; } block_idx++; } } }
/** Apply the transform to a buffer starting at "data". That buffer MUST be ROZOFS_BSIZE aligned. The first_block_idx is the index of a ROZOFS_BSIZE array in the output buffer The number_of_blocks is the number of ROZOFS_BSIZE that must be transform Notice that the first_block_idx offset applies to the output transform buffer only not to the input buffer pointed by "data". * * @param *prj_ctx_p: pointer to the working array of the projection * @param first_block_idx: index of the first block to transform * @param number_of_blocks: number of blocks to write * @param timestamp: date in microseconds @param last_block_size: effective length of the last block * @param *data: pointer to the source data that must be transformed * * @return: the length written on success, -1 otherwise (errno is set) */ int rozofs_storcli_transform_forward(rozofs_storcli_projection_ctx_t *prj_ctx_p, uint8_t layout,uint32_t bsize, uint32_t first_block_idx, uint32_t number_of_blocks, uint64_t timestamp, uint16_t last_block_size, char *data) { projection_t rozofs_fwd_projections[ROZOFS_SAFE_MAX_STORCLI]; projection_t *projections; // Table of projections used to transform data uint16_t projection_id = 0; uint32_t i = 0; uint8_t rozofs_forward = rozofs_get_rozofs_forward(layout); uint8_t rozofs_inverse = rozofs_get_rozofs_inverse(layout); int empty_block = 0; uint32_t bbytes = ROZOFS_BSIZE_BYTES(bsize); projections = rozofs_fwd_projections; int prj_size_in_msg = rozofs_get_max_psize_in_msg(layout,bsize); /* Transform the data */ // For each block to send for (i = 0; i < number_of_blocks; i++) { empty_block = rozofs_data_block_check_empty(data + (i * bbytes), bbytes); // seek bins for each projection for (projection_id = 0; projection_id < rozofs_forward; projection_id++) { /* ** Indicates the memory area where the transformed data must be stored */ projections[projection_id].bins = prj_ctx_p[projection_id].bins + (prj_size_in_msg/sizeof(bin_t)) * (first_block_idx+i); rozofs_stor_bins_hdr_t *rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t*)projections[projection_id].bins; rozofs_stor_bins_footer_t *rozofs_bins_foot_p = (rozofs_stor_bins_footer_t*) ((bin_t*)(rozofs_bins_hdr_p+1)+ rozofs_get_psizes(layout,bsize,projection_id)); /* ** check if the user data block is empty: if the data block is empty no need to transform */ if (empty_block) { rozofs_bins_hdr_p->s.projection_id = 0; rozofs_bins_hdr_p->s.timestamp = 0; rozofs_bins_hdr_p->s.effective_length = 0; rozofs_bins_hdr_p->s.filler = 0; rozofs_bins_hdr_p->s.version = 0; continue; } /* ** fill the header of the projection */ rozofs_bins_hdr_p->s.projection_id = projection_id; rozofs_bins_hdr_p->s.timestamp = timestamp; rozofs_bins_hdr_p->s.filler = 0; rozofs_bins_hdr_p->s.version = 0; /* ** set the effective size of the block. It is always ROZOFS_BSIZE except for the last block */ if (i == (number_of_blocks-1)) { rozofs_bins_hdr_p->s.effective_length = last_block_size; } else { rozofs_bins_hdr_p->s.effective_length = bbytes; } /* ** update the pointer to point out the first bins */ projections[projection_id].bins += sizeof(rozofs_stor_bins_hdr_t)/sizeof(bin_t); rozofs_bins_foot_p = (rozofs_stor_bins_footer_t*) (projections[projection_id].bins + rozofs_get_psizes(layout,bsize,projection_id)); rozofs_bins_foot_p->timestamp = timestamp; } /* ** do not apply transform for empty block */ if (empty_block == 0) { transform_forward_proc(layout,data + (i * bbytes),bbytes,projections); } } return 0; }
/** Apply the transform to a buffer starting at "data". That buffer MUST be ROZOFS_BSIZE aligned. The first_block_idx is the index of a ROZOFS_BSIZE array in the output buffer The number_of_blocks is the number of ROZOFS_BSIZE that must be transform Notice that the first_block_idx offset applies to the output transform buffer only not to the input buffer pointed by "data". * * @param *prj_ctx_p: pointer to the working array of the projection * @param first_block_idx: index of the first block to transform * @param number_of_blocks: number of blocks to write * @param *data: pointer to the source data that must be transformed @param *number_of_blocks_p: pointer to the array where the function returns number of blocks on which the transform was applied @param *rozofs_storcli_prj_idx_table: pointer to the array used for storing the projections index for inverse process * * @return: the length written on success, -1 otherwise (errno is set) */ int rozofs_storcli_transform_inverse(rozofs_storcli_projection_ctx_t *prj_ctx_p, uint8_t layout, uint32_t first_block_idx, uint32_t number_of_blocks, rozofs_storcli_inverse_block_t *block_ctx_p, char *data, uint32_t *number_of_blocks_p, uint8_t *rozofs_storcli_prj_idx_table) { projection_t *projections = NULL; projection_t rozofs_inv_projections[ROZOFS_SAFE_MAX]; int block_idx; uint16_t projection_id = 0; int prj_ctx_idx; *number_of_blocks_p = 0; uint8_t rozofs_inverse = rozofs_get_rozofs_inverse(layout); projections = rozofs_inv_projections; /* ** Proceed the inverse data transform for the nb_projections2read blocks. */ for (block_idx = 0; block_idx < number_of_blocks; block_idx++) { if (block_ctx_p[block_idx].state == ROZOFS_BLK_TRANSFORM_DONE) { /* ** transformation has already been done for that block of ROZOFS_BSIZE siz ** check the next one */ continue; } #if 0 /* ** check if we can find out a set of rozofs_inverse projections that will permit to ** rebuild the current block of ROZOFS_BSIZE sise ** For this we check if we can find at least rozofs_inverse projections with the same ** time stamp and with different angles(projection id ** If there is no enough valid projection we need to read a new projection on the next ** storage in sequence that follows the index of the last valid storage on which a projection has been ** read. ** It might be possible that we run out of storage since rozofs_safe has been reached and we have not reached ** rozofs_inserse projection!! */ ret = rozofs_storcli_transform_inverse_check(prj_ctx_p,layout, block_idx, rozofs_storcli_prj_idx_table, &block_ctx_p[block_idx].timestamp, &block_ctx_p[block_idx].effective_length); if (ret < 0) { /* ** the set of projection that have been read does not permit to rebuild, need to read more */ return -1; } #endif /* ** Check the case of the file that has no data (there is a hole in the file), this is indicated by ** reporting a timestamp of 0 */ if ((block_ctx_p[block_idx].timestamp == 0) && (block_ctx_p[block_idx].effective_length == ROZOFS_BSIZE )) { /* ** clear the memory */ ROZOFS_STORCLI_STATS(ROZOFS_STORCLI_EMPTY_READ); memset( data + (ROZOFS_BSIZE * (first_block_idx + block_idx)),0,ROZOFS_BSIZE); block_ctx_p[block_idx].state = ROZOFS_BLK_TRANSFORM_DONE; continue; } if ((block_ctx_p[block_idx].timestamp == 0) && (block_ctx_p[block_idx].effective_length == 0 )) { /* ** we have reached end of file */ block_ctx_p[block_idx].state = ROZOFS_BLK_TRANSFORM_DONE; *number_of_blocks_p = (block_idx++); return 0; } /* ** Here we have to take care, since the index of the projection_id use to address ** prj_ctx_p is NOT the real projection_id. The projection ID is found in the header of ** each bins, so for a set of projections pointed by bins, we might have a different ** projection id in the header of the projections contains in the bins array that has ** been read!! */ int prj_count = 0; for (prj_count = 0; prj_count < rozofs_inverse; prj_count++) { /* ** Get the pointer to the beginning of the projection and extract the projection Id */ prj_ctx_idx = rozofs_storcli_prj_idx_table[ROZOFS_SAFE_MAX*block_idx+prj_count]; rozofs_stor_bins_hdr_t *rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t*)(prj_ctx_p[prj_ctx_idx].bins +((rozofs_get_max_psize(layout)+(sizeof(rozofs_stor_bins_hdr_t)/sizeof(bin_t))) * block_idx)); /* ** Extract the projection_id from the header ** and Fill the table of projections for the block block_idx ** For each meta-projection */ projection_id = rozofs_bins_hdr_p->s.projection_id; projections[prj_count].angle.p = rozofs_get_angles_p(layout,projection_id); projections[prj_count].angle.q = rozofs_get_angles_q(layout,projection_id); projections[prj_count].size = rozofs_get_psizes(layout,projection_id); projections[prj_count].bins = (bin_t*)(rozofs_bins_hdr_p+1); } // Inverse data for the block (first_block_idx + block_idx) transform_inverse_inline((pxl_t *) (data + (ROZOFS_BSIZE * (first_block_idx + block_idx))), rozofs_inverse, ROZOFS_BSIZE / rozofs_inverse / sizeof (pxl_t), rozofs_inverse, projections); /* ** indicate that transform has been done for the projection */ block_ctx_p[block_idx].state = ROZOFS_BLK_TRANSFORM_DONE; /* ** check the case of a block that is not full: need to zero's that part */ if (block_ctx_p[block_idx].effective_length < ROZOFS_BSIZE) { /* ** clear the memory */ char *raz_p = data + (ROZOFS_BSIZE * (first_block_idx + block_idx)) + block_ctx_p[block_idx].effective_length; memset( raz_p,0,(ROZOFS_BSIZE-block_ctx_p[block_idx].effective_length) ); } } /* ** now the inverse transform is finished, release the allocated ressources used for ** rebuild */ *number_of_blocks_p = number_of_blocks; return 0; }
/** Apply the transform to a buffer starting at "data". That buffer MUST be ROZOFS_BSIZE aligned. The first_block_idx is the index of a ROZOFS_BSIZE array in the output buffer The number_of_blocks is the number of ROZOFS_BSIZE that must be transform Notice that the first_block_idx offset applies to the output transform buffer only not to the input buffer pointed by "data". * * @param *prj_ctx_p: pointer to the working array of the projection * @param first_block_idx: index of the first block to transform * @param number_of_blocks: number of blocks to write * @param timestamp: date in microseconds @param last_block_size: effective length of the last block * @param *data: pointer to the source data that must be transformed * * @return: the length written on success, -1 otherwise (errno is set) */ int rozofs_storcli_transform_forward(rozofs_storcli_projection_ctx_t *prj_ctx_p, uint8_t layout, uint32_t first_block_idx, uint32_t number_of_blocks, uint64_t timestamp, uint16_t last_block_size, char *data) { projection_t rozofs_fwd_projections[ROZOFS_SAFE_MAX]; projection_t *projections; // Table of projections used to transform data uint16_t projection_id = 0; uint32_t i = 0; uint8_t rozofs_forward = rozofs_get_rozofs_forward(layout); uint8_t rozofs_inverse = rozofs_get_rozofs_inverse(layout); int empty_block = 0; projections = rozofs_fwd_projections; // For each projection for (projection_id = 0; projection_id < rozofs_forward; projection_id++) { projections[projection_id].angle.p = rozofs_get_angles_p(layout,projection_id); projections[projection_id].angle.q = rozofs_get_angles_q(layout,projection_id); projections[projection_id].size = rozofs_get_psizes(layout,projection_id); } /* Transform the data */ // For each block to send for (i = 0; i < number_of_blocks; i++) { empty_block = rozofs_data_block_check_empty(data + (i * ROZOFS_BSIZE), ROZOFS_BSIZE); // seek bins for each projection for (projection_id = 0; projection_id < rozofs_forward; projection_id++) { /* ** Indicates the memory area where the transformed data must be stored */ projections[projection_id].bins = prj_ctx_p[projection_id].bins + ((rozofs_get_max_psize(layout)+(sizeof(rozofs_stor_bins_hdr_t)/sizeof(bin_t)))* (first_block_idx+i)); rozofs_stor_bins_hdr_t *rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t*)projections[projection_id].bins; /* ** check if the user data block is empty: if the data block is empty no need to transform */ if (empty_block) { rozofs_bins_hdr_p->s.projection_id = 0; rozofs_bins_hdr_p->s.timestamp = 0; rozofs_bins_hdr_p->s.effective_length = 0; continue; } /* ** fill the header of the projection */ rozofs_bins_hdr_p->s.projection_id = projection_id; rozofs_bins_hdr_p->s.timestamp = timestamp; /* ** set the effective size of the block. It is always ROZOFS_BSIZE except for the last block */ if (i == (number_of_blocks-1)) { rozofs_bins_hdr_p->s.effective_length = last_block_size; } else { rozofs_bins_hdr_p->s.effective_length = ROZOFS_BSIZE; } /* ** update the pointer to point out the first bins */ projections[projection_id].bins += sizeof(rozofs_stor_bins_hdr_t)/sizeof(bin_t); } /* ** do not apply transform for empty block */ if (empty_block == 0) { /* ** Apply the erasure code transform for the block i+first_block_idx */ transform_forward((pxl_t *) (data + (i * ROZOFS_BSIZE)), rozofs_inverse, ROZOFS_BSIZE / rozofs_inverse / sizeof (pxl_t), rozofs_forward, projections); } } return 0; }
int read_data_file() { int status = -1; uint64_t size = 0; int block_idx = 0; int idx =0; int count; rozofs_stor_bins_hdr_t * rozofs_bins_hdr_p; rozofs_stor_bins_footer_t * rozofs_bins_foot_p; char * loc_read_bins_p = NULL; int forward = rozofs_get_rozofs_forward(layout); // int inverse = rozofs_get_rozofs_inverse(layout); uint16_t disk_block_size; uint16_t max_block_size = (rozofs_get_max_psize(layout,bsize)*sizeof (bin_t)) + sizeof (rozofs_stor_bins_hdr_t) + sizeof (rozofs_stor_bins_footer_t); char * p; int empty,valid; int prj_id; int nb_ts; uint64_t ts[32]; int ts_count[32]; // Allocate memory for reading loc_read_bins_p = xmalloc(max_block_size); for (idx=0; idx < nb_file; idx++) { if (strcmp(filename[idx],"NULL") == 0) { fd[idx] = -1; } else { fd[idx] = open(filename[idx],O_RDWR); if (fd < 0) { severe("Can not open file %s %s",filename[idx],strerror(errno)); goto out; } } } printf (" ______ __________ "); for (idx=0; idx < nb_file; idx++) printf (" __________________ ______ ____ "); printf ("\n"); printf("| %4s | %8s |","Blk","Offset"); for (idx=0; idx < nb_file; idx++) printf("| %16s | %4s | %2s |", "Time stamp", "lgth", "id"); printf ("\n"); printf ("|______|__________|"); for (idx=0; idx < nb_file; idx++) printf ("|__________________|______|____|"); printf ("\n"); if (block_number == -1) block_idx = 0; else block_idx = block_number; count = 1; empty = 0; while ( count ) { valid = 0; count = 0; nb_ts = 0; p = &LINE[0]; p += sprintf(p,"| %4d | %8d ",block_idx+firstBlock,(block_idx+firstBlock)*bbytes); for (idx=0; idx < nb_file; idx++) { if (fd[idx] == -1) { p += sprintf(p,"%32s"," "); continue; } if (idx >= forward) disk_block_size = rozofs_get_max_psize_in_msg(layout, bsize); else disk_block_size = rozofs_get_psizes_on_disk(layout,bsize,idx); size = pread(fd[idx],loc_read_bins_p,disk_block_size,block_idx*disk_block_size); if (size != disk_block_size) { p += sprintf(p,"|__________________|______|____|"); close(fd[idx]); fd[idx] = -1; } else { count++; rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t *)loc_read_bins_p; prj_id = rozofs_bins_hdr_p->s.projection_id; if (prj_id >= forward) { valid = 1; p += sprintf(p,"|| xxxxxxxxxxxxxxxx | xxxx | %2d ",prj_id); } else { disk_block_size = (rozofs_get_psizes(layout,bsize,prj_id)*sizeof (bin_t)); disk_block_size += sizeof (rozofs_stor_bins_hdr_t); rozofs_bins_foot_p = (rozofs_stor_bins_footer_t *) ((char*) rozofs_bins_hdr_p + disk_block_size); if (rozofs_bins_hdr_p->s.timestamp == 0) { p += sprintf(p,"|| %16d | .... | %2d ",0,prj_id); } else if (rozofs_bins_foot_p->timestamp != rozofs_bins_hdr_p->s.timestamp) { valid = 1; p += sprintf(p,"|--%16.16llu----------%2d-", (long long unsigned int)rozofs_bins_hdr_p->s.timestamp, prj_id); } else if (rozofs_bins_hdr_p->s.timestamp == 0) { p += sprintf(p,"|| %16d | .... | %2d ",0,prj_id); } else { valid = 1; p += sprintf(p,"|| %16llu | %4d | %2d ", (unsigned long long)rozofs_bins_hdr_p->s.timestamp, rozofs_bins_hdr_p->s.effective_length, rozofs_bins_hdr_p->s.projection_id); int tsidx; for (tsidx=0; tsidx< nb_ts; tsidx++) { if (ts[tsidx] == rozofs_bins_hdr_p->s.timestamp) { ts_count[tsidx]++; break; } } if (tsidx == nb_ts) { ts[tsidx] = rozofs_bins_hdr_p->s.timestamp; ts_count[tsidx] = 1; nb_ts++; } } } } } if (valid) { if (empty) { printf("... %d blocks...\n",empty); empty = 0; } int best=-1,tsidx; for (tsidx=0; tsidx< nb_ts; tsidx++) { if (ts_count[tsidx] > best) best = ts_count[tsidx]; } printf("%s%s\n",LINE, (best<forward)?"<<<<----":"|"); } else { empty++; } block_idx++; if (block_number!=-1) break; } printf ("|______|__________|\n"); if (block_number!=-1) { for (idx=0; idx < nb_file; idx++) { if (idx < forward) { disk_block_size = (rozofs_get_psizes(layout,bsize,idx)*sizeof (bin_t)) + sizeof (rozofs_stor_bins_hdr_t) + sizeof (rozofs_stor_bins_footer_t); } else { disk_block_size = (rozofs_get_max_psize(layout,bsize)*sizeof (bin_t)) + sizeof (rozofs_stor_bins_hdr_t) + sizeof (rozofs_stor_bins_footer_t); } size = pread(fd[idx],loc_read_bins_p,disk_block_size,block_number*disk_block_size); if (size != disk_block_size) { printf("Can not read block %d of %s\n", block_number, filename[idx]); continue; } FILE * f; char fname[128]; sprintf(fname,"block_%d_dist_%d.txt", block_number, idx); f = fopen(fname,"w"); if (f == NULL) { printf ("Can not create file %s",fname); continue; } printf("- %s\n",fname); fprintf(f,"%s Block %d size %d\n", filename[idx], block_number, disk_block_size); rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t *)loc_read_bins_p; fprintf(f,"Block header : TS %llu SZ %d PRJ %d CRC32 0x%x\n", (long long unsigned int)rozofs_bins_hdr_p->s.timestamp, rozofs_bins_hdr_p->s.effective_length, rozofs_bins_hdr_p->s.projection_id, rozofs_bins_hdr_p->s.filler); rozofs_bins_foot_p = (rozofs_stor_bins_footer_t *) (loc_read_bins_p + disk_block_size); rozofs_bins_foot_p--; fprintf(f,"Block footer : TS %llu %s\n", (long long unsigned int)rozofs_bins_foot_p->timestamp, (rozofs_bins_hdr_p->s.timestamp==rozofs_bins_foot_p->timestamp)?"":" !!!!!!"); hexdump(f,loc_read_bins_p, 0, disk_block_size); fclose(f); } } status = 0; out: // This spare file used to exist but is not needed any more for (idx=0; idx < nb_file; idx++) { if (fd[idx] != -1) close(fd[idx]); } if (loc_read_bins_p != NULL) { //free(loc_read_bins_p); loc_read_bins_p = NULL; } return status; }