Example #1
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 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 *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++;    	  
        }
    }
}
Example #3
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 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;
}
Example #4
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;
}
Example #5
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;   
}
Example #6
0
inline int rozofs_storcli_transform_inverse_check(rozofs_storcli_projection_ctx_t *prj_ctx_p,  
                                       uint8_t layout,
                                       uint32_t block_idx, 
                                       uint8_t *prj_idx_tb_p,
                                       uint64_t *timestamp_p,
                                       uint16_t *effective_len_p)
{
    uint8_t prj_ctx_idx;
    uint8_t nb_projection_with_same_timestamp = 0;
    uint8_t rozofs_inverse = rozofs_get_rozofs_inverse(layout);
    uint8_t rozofs_safe = rozofs_get_rozofs_safe(layout);
    int ret;
    int eof = 1;
    *timestamp_p = 0;
    *effective_len_p = 0;
    rozofs_storcli_timestamp_ctx_t ref_ctx;        
    rozofs_storcli_timestamp_ctx_t *ref_ctx_p = &ref_ctx;        
    rozofs_storcli_timestamp_ctx_t rozofs_storcli_timestamp_tb[ROZOFS_SAFE_MAX];
    uint8_t  rozofs_storcli_timestamp_next_free_idx=0;
    
    ref_ctx_p->count = 0;
    /*
    ** clean data used for tracking projection to rebuild
    */
    rozofs_storcli_timestamp_ctx_t *p = &rozofs_storcli_timestamp_tb[rozofs_storcli_timestamp_next_free_idx];        
    p->timestamp = 0;
    p->count     = 0;

    for (prj_ctx_idx = 0; prj_ctx_idx < rozofs_safe; prj_ctx_idx++)
    {
      if (prj_ctx_p[prj_ctx_idx].prj_state != ROZOFS_PRJ_READ_DONE)
      {
        /*
        ** that projection context does not contain valid data, so skip it
        */
        continue;      
      }
      /*
      ** Get the pointer to the projection header
      */
      rozofs_stor_bins_hdr_t *rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t*)&prj_ctx_p[prj_ctx_idx].block_hdr_tab[block_idx];
      /*
      ** skip the invalid blocks
      */
      if ((rozofs_bins_hdr_p->s.timestamp == 0) && (rozofs_bins_hdr_p->s.effective_length==0)) continue;
      if (ref_ctx_p->count == 0)
      {
        /*
        ** first projection found
        */
        eof = 0;
        ref_ctx_p->timestamp     = rozofs_bins_hdr_p->s.timestamp;
        ref_ctx_p->effective_length = rozofs_bins_hdr_p->s.effective_length;
        ref_ctx_p->count++;
        prj_idx_tb_p[nb_projection_with_same_timestamp++] = prj_ctx_idx; 
        continue;            
      }
      /*
      ** the entry is not empty check if the timestamp and the effective length of the block belonging to 
      ** projection prj_ctx_idx matches
      */
      if ((rozofs_bins_hdr_p->s.timestamp == ref_ctx_p->timestamp) &&(rozofs_bins_hdr_p->s.effective_length == ref_ctx_p->effective_length))
      {
        /*
        ** there is a match, store the projection index and check if we have reach rozofs_inverse blocks with the 
        ** same timestamp and length
        */
        ref_ctx_p->count++;
        prj_idx_tb_p[nb_projection_with_same_timestamp++] = prj_ctx_idx; 

        if (nb_projection_with_same_timestamp == rozofs_inverse)
        {
          /*
          ** ok we have found all the projection for the best case
          */
          *timestamp_p     = ref_ctx_p->timestamp;
          *effective_len_p = ref_ctx_p->effective_length;
          /*
          ** Mark the projection that MUST be rebuilt
          */
          if (rozofs_storcli_timestamp_next_free_idx)
          {
             rozofs_storcli_mark_projection2rebuild(prj_ctx_p,
                                                    rozofs_storcli_timestamp_tb,
                                                    rozofs_storcli_timestamp_next_free_idx+1,
                                                    rozofs_storcli_timestamp_next_free_idx);
          }
          return (int)rozofs_inverse;        
        }
        continue;      
      }
      /*
      ** Either the length of the timestamp does not match
      ** log the reference of the projection index in order to address a potential rebuild of the
      ** projection
      */
      p->prj_idx_tb[p->count]= prj_ctx_idx;
      p->count++;
      if (rozofs_storcli_timestamp_next_free_idx == 0)
      {
         rozofs_storcli_timestamp_next_free_idx = 1;
      }        
    }
    /*
    ** check th eof case
    */
    if (eof) return 0;
    /*
    ** unlucky, we did not find rozof_inverse projections with the same timestamp
    ** so we have to find out the projection(s) that are out of sequence
    */
    ret =  rozofs_storcli_transform_inverse_check_timestamp_tb( prj_ctx_p,  
                                        layout,
                                        block_idx, 
                                        prj_idx_tb_p,
                                        timestamp_p,
                                        effective_len_p);
    return ret;
}
Example #7
0
inline int rozofs_storcli_transform_inverse_check_timestamp_tb(rozofs_storcli_projection_ctx_t *prj_ctx_p,  
                                       uint8_t layout,
                                       uint32_t block_idx, 
                                       uint8_t *prj_idx_tb_p,
                                       uint64_t *timestamp_p,
                                       uint16_t *effective_len_p)
{
    uint8_t prj_ctx_idx;
    uint8_t timestamp_entry;
    *timestamp_p = 0;
    uint8_t rozofs_inverse = rozofs_get_rozofs_inverse(layout);
    uint8_t rozofs_safe = rozofs_get_rozofs_safe(layout);
    rozofs_storcli_timestamp_ctx_t *p;
    int eof = 1;
    rozofs_storcli_timestamp_ctx_t rozofs_storcli_timestamp_tb[ROZOFS_SAFE_MAX];
    uint8_t  rozofs_storcli_timestamp_next_free_idx=0;

    for (prj_ctx_idx = 0; prj_ctx_idx < rozofs_safe; prj_ctx_idx++)
    {
      if (prj_ctx_p[prj_ctx_idx].prj_state != ROZOFS_PRJ_READ_DONE)
      {
        /*
        ** that projection context does not contain valid data, so skip it
        */
        continue;      
      }
      /*
      ** Get the pointer to the projection header
      */      
      rozofs_stor_bins_hdr_t *rozofs_bins_hdr_p = (rozofs_stor_bins_hdr_t*)&prj_ctx_p[prj_ctx_idx].block_hdr_tab[block_idx];
      /*
      ** check if the current block of the projection contains valid data. The block is invalid when the timestamp and the
      ** effective length are 0. That situation can occur when a storage was in fault at the writing time, so we can face
      ** the situation where the projections read on the different storages do not return the same number of block.
      */
      if ((rozofs_bins_hdr_p->s.timestamp == 0)&&(rozofs_bins_hdr_p->s.effective_length == 0))  continue;
      if (rozofs_storcli_timestamp_next_free_idx == 0)
      {
        /*
        ** first entry
        */
        eof = 0;
        p = &rozofs_storcli_timestamp_tb[rozofs_storcli_timestamp_next_free_idx];        
        p->timestamp     = rozofs_bins_hdr_p->s.timestamp;
        p->effective_length = rozofs_bins_hdr_p->s.effective_length;
        p->count         = 0;
        p->prj_idx_tb[p->count]= prj_ctx_idx;
        p->count++;
        rozofs_storcli_timestamp_next_free_idx++;
        continue;      
      }
      /*
      ** more than 1 entry in the timestamp table
      */
      for(timestamp_entry = 0; timestamp_entry < rozofs_storcli_timestamp_next_free_idx;timestamp_entry++)
      {
        p = &rozofs_storcli_timestamp_tb[timestamp_entry];        
        if ((rozofs_bins_hdr_p->s.timestamp != p->timestamp) || (rozofs_bins_hdr_p->s.effective_length != p->effective_length)) continue;
        /*
        ** same timestamp and length: register the projection index and check if we have reached rozofs_inverse projections
        ** to stop the search
        */
        p->prj_idx_tb[p->count]= prj_ctx_idx;
        p->count++;
        if (p->count == rozofs_inverse)
        {
          /*
          ** OK we have the right number of projection so we can leave
          */
          memcpy(prj_idx_tb_p,p->prj_idx_tb,rozofs_inverse);
          /*
          ** assert the timestamp that is common to all projections used to rebuild that block
          */
          *timestamp_p     = p->timestamp;
          *effective_len_p = p->effective_length;
          /*
          ** Mark the projection that MUST be rebuilt
          */
          rozofs_storcli_mark_projection2rebuild(prj_ctx_p,rozofs_storcli_timestamp_tb,timestamp_entry,rozofs_storcli_timestamp_next_free_idx);
          return 1;       
        }
        /*
        ** try next
        */
      }
      /*
      ** that timestamp does not exist, so create an entry for it
      */
      p = &rozofs_storcli_timestamp_tb[rozofs_storcli_timestamp_next_free_idx];        
      p->timestamp     = rozofs_bins_hdr_p->s.timestamp;
      p->effective_length = rozofs_bins_hdr_p->s.effective_length;
      p->count     = 0;
      p->prj_idx_tb[p->count]= prj_ctx_idx;
      p->count++;
      rozofs_storcli_timestamp_next_free_idx++;
    }
    /*
    ** take care of the case where we try to read after the end of file
    */
    if (eof) return 0;
    /*
    ** unlucky, we did not find rozof_inverse projections with the same timestamp
    ** we need to read one more projection unless we already attempt to read rozofs_safe
    ** projection or we run out of storage that are up among the set of rozofs_safe storage   
    */
    return -1;

}