/** * That function check if the user data block to transform is empty @param data: pointer to the user data block : must be aligned on a 8 byte boundary @param size: size of the data block (must be blocksize aligned) @retval 0 non empty @retval 1 empty */ static inline int rozofs_data_block_check_empty(char *data, int size) { uint64_t *p64; int i; p64 = (uint64_t*) data; for (i = 0; i < (size/sizeof(uint64_t));i++,p64++) { if (*p64 != 0) return 0; } ROZOFS_STORCLI_STATS(ROZOFS_STORCLI_EMPTY_WRITE); return 1; }
/** 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 bsize, 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) { 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); uint8_t rozofs_forward = rozofs_get_rozofs_forward(layout); uint8_t rozofs_safe = rozofs_get_rozofs_safe(layout); uint32_t bbytes = ROZOFS_BSIZE_BYTES(bsize); int prj_size_in_msg = rozofs_get_max_psize_in_msg(layout,bsize); /* ** 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; } /* ** 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 == bbytes )) { /* ** clear the memory */ ROZOFS_STORCLI_STATS(ROZOFS_STORCLI_EMPTY_READ); memset( data + (bbytes * (first_block_idx + block_idx)),0,bbytes); 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!! */ transform_inverse_proc(&rozofs_storcli_prj_idx_table[ROZOFS_SAFE_MAX_STORCLI*block_idx], prj_ctx_p, prj_size_in_msg, layout, bbytes, first_block_idx, block_idx, data); /* ** 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 < bbytes) { /* ** clear the memory */ char *raz_p = data + (bbytes * (first_block_idx + block_idx)) + block_ctx_p[block_idx].effective_length; memset( raz_p,0,(bbytes-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; /* ** Check whether a block should be repaired */ rozofs_storcli_check_block_2_repair(prj_ctx_p, rozofs_inverse, rozofs_forward, rozofs_safe, prj_size_in_msg, number_of_blocks, block_ctx_p); 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; }