/** 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++; } } }
/** 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; }
int export_unlink_multiple(export_t * e, fid_t parent, char *name, fid_t fid,mattr_t * pattrs,lv2_entry_t *plv2) { int status = -1; lv2_entry_t *lv2=NULL; fid_t child_fid; uint32_t child_type; uint16_t nlink = 0; int fdp = -1; int ret; rozofs_inode_t *fake_inode_p; rmfentry_disk_t trash_entry; int root_dirent_mask = 0; int unknown_fid = 0; int deleted_fid_count = 0; char filename[1024]; char *basename; int filecount; char *filename_p; int k; /* ** search for rozofs key in the filename */ if (strncmp(name,".@rozofs-mf@",12) == 0) { ret = rozofs_parse_object_name((char*)(name+12),&basename,&filecount); if (ret < 0) { errno = ENOTSUP; goto error; } } /* ** load the root_idx bitmap of the old parent */ export_dir_load_root_idx_bitmap(e,parent,plv2); /* ** set global variables associated with the export */ fdp = export_open_parent_directory(e,parent); if (get_mdirentry(plv2->dirent_root_idx_p,fdp, parent, name, child_fid, &child_type,&root_dirent_mask) != 0) goto out; if (S_ISDIR(child_type)) { errno = EISDIR; goto out; } /* ** do a loop on the file count */ for (k = 0; k < filecount ; k++) { sprintf(filename,"%s.%d",basename,k); filename_p = filename; // Delete the mdirentry if exist ret =del_mdirentry(plv2->dirent_root_idx_p,fdp, parent, name, child_fid, &child_type,root_dirent_mask); if (ret != 0) { if (errno != ENOENT) goto out; /* ** check the next entry */ continue; } // Get mattrs of child to delete if (!(lv2 = export_lookup_fid(e->trk_tb_p,e->lv2_cache, child_fid))) { unknown_fid++; /* ** check the next entry */ continue; } deleted_fid_count++; // Compute hash value for this fid uint32_t hash = 0; uint8_t *c = 0; for (c = lv2->attributes.s.attrs.fid; c != lv2->attributes.s.attrs.fid + 16; c++) hash = *c + (hash << 6) + (hash << 16) - hash; hash %= RM_MAX_BUCKETS; /* ** prepare the trash entry */ trash_entry.size = lv2->attributes.s.attrs.size; memcpy(trash_entry.fid, lv2->attributes.s.attrs.fid, sizeof (fid_t)); trash_entry.cid = lv2->attributes.s.attrs.cid; memcpy(trash_entry.initial_dist_set, lv2->attributes.s.attrs.sids, sizeof (sid_t) * ROZOFS_SAFE_MAX); memcpy(trash_entry.current_dist_set, lv2->attributes.s.attrs.sids, sizeof (sid_t) * ROZOFS_SAFE_MAX); fake_inode_p = (rozofs_inode_t *)parent; ret = exp_trash_entry_create(e->trk_tb_p,fake_inode_p->s.usr_id,&trash_entry); if (ret < 0) { /* ** error while inserting entry in trash file */ severe("error on trash insertion name %s error %s",name,strerror(errno)); } /* ** delete the metadata associated with the file */ ret = exp_delete_file(e,lv2); /* * In case of geo replication, insert a delete request from the 2 sites */ if (e->volume->georep) { /* ** update the geo replication: set start=end=0 to indicate a deletion */ geo_rep_insert_fid(e->geo_replication_tb[0], lv2->attributes.s.attrs.fid, 0/*start*/,0/*end*/, e->layout, lv2->attributes.s.attrs.cid, lv2->attributes.s.attrs.sids); /* ** update the geo replication: set start=end=0 to indicate a deletion */ geo_rep_insert_fid(e->geo_replication_tb[1], lv2->attributes.s.attrs.fid, 0/*start*/,0/*end*/, e->layout, lv2->attributes.s.attrs.cid, lv2->attributes.s.attrs.sids); } /* ** Preparation of the rmfentry */ rmfentry_t *rmfe = xmalloc(sizeof (rmfentry_t)); export_rm_bins_pending_count++; memcpy(rmfe->fid, trash_entry.fid, sizeof (fid_t)); rmfe->cid = trash_entry.cid; memcpy(rmfe->initial_dist_set, trash_entry.initial_dist_set, sizeof (sid_t) * ROZOFS_SAFE_MAX); memcpy(rmfe->current_dist_set, trash_entry.current_dist_set, sizeof (sid_t) * ROZOFS_SAFE_MAX); memcpy(rmfe->trash_inode,trash_entry.trash_inode,sizeof(fid_t)); list_init(&rmfe->list); /* Acquire lock on bucket trash list */ if ((errno = pthread_rwlock_wrlock (&e->trash_buckets[hash].rm_lock)) != 0) { severe("pthread_rwlock_wrlock failed: %s", strerror(errno)); // Best effort } /* ** Check size of file */ if (lv2->attributes.s.attrs.size >= RM_FILE_SIZE_TRESHOLD) { // Add to front of list list_push_front(&e->trash_buckets[hash].rmfiles, &rmfe->list); } else { // Add to back of list list_push_back(&e->trash_buckets[hash].rmfiles, &rmfe->list); } if ((errno = pthread_rwlock_unlock (&e->trash_buckets[hash].rm_lock)) != 0) { severe("pthread_rwlock_unlock failed: %s", strerror(errno)); // Best effort } // Update the nb. of blocks if (export_update_blocks(e, -(((int64_t) lv2->attributes.s.attrs.size + ROZOFS_BSIZE_BYTES(e->bsize) - 1) / ROZOFS_BSIZE_BYTES(e->bsize))) != 0) { severe("export_update_blocks failed: %s", strerror(errno)); // Best effort } // Remove from the cache (will be closed and freed) lv2_cache_del(e->lv2_cache, child_fid); } /* ** al the subfile have been deleted so Update export files */ if (export_update_files(e, 0-deleted_fid_count) != 0) goto out; // Update parent plv2->attributes.s.attrs.mtime = plv2->attributes.s.attrs.ctime = time(NULL); plv2->attributes.s.attrs.children--; // Write attributes of parents if (export_lv2_write_attributes(e->trk_tb_p,plv2) != 0) goto out; /* ** return the parent attributes */ memcpy(pattrs, &plv2->attributes.s.attrs, sizeof (mattr_t)); status = 0; out: /* ** check if parent root idx bitmap must be updated */ if (plv2 != NULL) export_dir_flush_root_idx_bitmap(e,parent,plv2->dirent_root_idx_p); if(fdp != -1) close(fdp); return status; }
/** * callback for the internal read request triggered by a truncate potential failure case: - socket_ref is out of range - connection is down @param buffer : pointer to the ruc_buffer that cointains the response @param socket_ref : non significant @param user_param_p : pointer to the root context @retval 0 : successfully submitted to the transport layer @retval < 0 error, the caller is intended to release the buffer */ int rozofs_storcli_internal_read_before_truncate_rsp_cbk(void *buffer,uint32_t socket_ref,void *user_param) { int errcode = 0; rozofs_storcli_ctx_t *working_ctx_p = (rozofs_storcli_ctx_t*)user_param; storcli_truncate_arg_t * storcli_truncate_rq_p = (storcli_truncate_arg_t*)&working_ctx_p->storcli_truncate_arg; XDR xdrs; uint8_t *payload; char *data; int position; int bufsize; struct rpc_msg rpc_reply; storcli_status_ret_t rozofs_status; int data_len; int error; rpc_reply.acpted_rply.ar_results.proc = NULL; uint32_t bsize = storcli_truncate_rq_p->bsize; uint32_t bbytes = ROZOFS_BSIZE_BYTES(bsize); /* ** decode the read internal read reply */ payload = (uint8_t*) ruc_buf_getPayload(buffer); payload += sizeof(uint32_t); /* skip length*/ /* ** OK now decode the received message */ bufsize = ruc_buf_getPayloadLen(buffer); bufsize -= sizeof(uint32_t); /* skip length*/ xdrmem_create(&xdrs,(char*)payload,bufsize,XDR_DECODE); error = 0; while (1) { /* ** decode the rpc part */ if (rozofs_xdr_replymsg(&xdrs,&rpc_reply) != TRUE) { errno = EPROTO; error = 1; break; } /* ** decode the status of the operation */ if (xdr_storcli_status_ret_t(&xdrs,&rozofs_status)!= TRUE) { errno = EPROTO; error = 1; break; } /* ** check th estatus of the operation */ if ( rozofs_status.status != STORCLI_SUCCESS ) { error = 0; break; } { int alignment; int k; /* ** skip the alignment */ for (k=0; k<3; k++) { if (xdr_int(&xdrs, &alignment) != TRUE) { errno = EPROTO; STORCLI_ERR_PROF(read_prj_err); error = 1; break; } } if (error==1) break; } /* ** Now get the length of the part that has been read */ if (xdr_int(&xdrs, &data_len) != TRUE) { errno = EPROTO; error = 1; break; } break; } if (error) { severe("error while decoding rpc reply"); goto failure; } position = XDR_GETPOS(&xdrs); data = (char*)(payload+position); /* ** check the status of the read operation */ if (rozofs_status.status != STORCLI_SUCCESS) { data = NULL; } else { /*, ** No data returned */ if (data_len == 0) { data = NULL; } else if (storcli_truncate_rq_p->last_seg <= data_len) { memset(data+storcli_truncate_rq_p->last_seg, 0, bbytes-storcli_truncate_rq_p->last_seg); } else { memset(data+data_len, 0, bbytes-data_len); } } rozofs_storcli_truncate_req_processing_exec(working_ctx_p, data); ruc_buf_freeBuffer(buffer); return 0 ; failure: ruc_buf_freeBuffer(buffer); /* ** check if the lock is asserted to prevent direct call to callback */ if (working_ctx_p->write_ctx_lock == 1) return 0; /* ** write failure */ rozofs_storcli_write_reply_error(working_ctx_p,errcode); /* ** release the transaction root context */ working_ctx_p->xmitBuf = NULL; STORCLI_STOP_NORTH_PROF(working_ctx_p,truncate,0); rozofs_storcli_release_context(working_ctx_p); return 0 ; }
void read_chunk_file(uuid_t fid, char * path, rozofs_stor_bins_file_hdr_vall_t * hdr, int spare, uint64_t firstBlock) { uint16_t rozofs_disk_psize; int fd; rozofs_stor_bins_hdr_t * pH; int nb_read; uint32_t bbytes = ROZOFS_BSIZE_BYTES(hdr->v0.bsize); char crc32_string[32]; uint64_t offset; if (dump_data == 0) { printf ("+------------+------------------+------------+----+------+-------+--------------------------------------------\n"); printf ("| %10s | %16s | %10s | %2s | %4s | %5s | %s\n", "block#","file offset", "prj offset", "pj", "size", "crc32", "date"); printf ("+------------+------------------+------------+----+------+-------+--------------------------------------------\n"); } // Open bins file fd = open(path, ROZOFS_ST_NO_CREATE_FILE_FLAG, ROZOFS_ST_BINS_FILE_MODE_RO); if (fd < 0) { printf("open(%s) %s\n",path,strerror(errno)); return; } /* ** Retrieve the projection size on disk */ rozofs_disk_psize = rozofs_get_max_psize_in_msg(hdr->v0.layout,hdr->v0.bsize); if (spare==0) { /* Header version 1. Find the sid in the distribution */ if (hdr->v0.version == 2) { int fwd = rozofs_get_rozofs_forward(hdr->v2.layout); int idx; for (idx=0; idx< fwd;idx++) { if (hdr->v2.distrib[idx] != hdr->v2.sid) continue; rozofs_disk_psize = rozofs_get_psizes_on_disk(hdr->v2.layout,hdr->v2.bsize,idx); break; } } else if (hdr->v0.version == 1) { int fwd = rozofs_get_rozofs_forward(hdr->v1.layout); int idx; for (idx=0; idx< fwd;idx++) { if (hdr->v1.dist_set_current[idx] != hdr->v1.sid) continue; rozofs_disk_psize = rozofs_get_psizes_on_disk(hdr->v1.layout,hdr->v1.bsize,idx); break; } } /* Projection id given as parameter */ else if (prjid != -1) { rozofs_disk_psize = rozofs_get_psizes_on_disk(hdr->v0.layout,hdr->v0.bsize,prjid); } /*�Version 0 without projection given as parameter*/ else { // Read 1rst block nb_read = pread(fd, buffer, sizeof(rozofs_stor_bins_hdr_t), 0); if (nb_read<0) { printf("pread(%s) %s\n",path,strerror(errno)); return; } pH = (rozofs_stor_bins_hdr_t*)buffer; if (pH->s.timestamp == 0) { printf("Can not tell projection id\n"); return; } rozofs_disk_psize = rozofs_get_psizes_on_disk(hdr->v0.layout,hdr->v0.bsize,pH->s.projection_id); } } /* ** Where to start reading from */ if (first == 0) { offset = 0; } else { if (first <= firstBlock) { offset = 0; } else { offset = (first-firstBlock)*rozofs_disk_psize; } } int idx; nb_read = 1; uint64_t bid; /* ** Reading blocks */ while (nb_read) { // Read nb_proj * (projection + header) nb_read = pread(fd, buffer, rozofs_disk_psize*32, offset); if (nb_read<0) { printf("pread(%s) %s\n",path,strerror(errno)); close(fd); return; } nb_read = (nb_read / rozofs_disk_psize); pH = (rozofs_stor_bins_hdr_t*) buffer; for (idx=0; idx<nb_read; idx++) { pH = (rozofs_stor_bins_hdr_t*) &buffer[idx*rozofs_disk_psize]; bid = (offset/rozofs_disk_psize)+idx+firstBlock; if (bid < first) continue; if (bid > last) break; uint32_t save_crc32 = pH->s.filler; pH->s.filler = 0; uint32_t crc32=0; if (save_crc32 == 0) { sprintf(crc32_string,"NONE"); } else { crc32 = fid2crc32((uint32_t *)fid)+bid-firstBlock; crc32 = crc32c(crc32,(char *) pH, rozofs_disk_psize); if (crc32 != save_crc32) sprintf(crc32_string,"ERROR"); else sprintf(crc32_string,"OK"); } pH->s.filler = save_crc32; if (dump_data == 0) { printf ("| %10llu | %16llu | %10llu | %2d | %4d | %5s | %s\n", (long long unsigned int)bid, (long long unsigned int)bbytes * bid, (long long unsigned int)offset+(idx*rozofs_disk_psize), pH->s.projection_id, pH->s.effective_length, crc32_string, ts2string(pH->s.timestamp)); } else { printf("_________________________________________________________________________________________\n"); printf("Block# %llu / file offset %llu / projection offset %llu\n", (unsigned long long)bid, (unsigned long long)(bbytes * bid), (unsigned long long)(offset+(idx*rozofs_disk_psize))); printf("prj id %d / length %d / CRC %s / time stamp %s\n", pH->s.projection_id,pH->s.effective_length,crc32_string, ts2string(pH->s.timestamp)); printf("_________________________________________________________________________________________\n"); if ((pH->s.projection_id == 0)&&(pH->s.timestamp==0)) continue; hexdump(pH, (offset+(idx*rozofs_disk_psize)), rozofs_disk_psize); } } offset += (nb_read*rozofs_disk_psize); } if (dump_data == 0) { printf ("+------------+------------------+------------+----+------+-------+--------------------------------------------\n"); } close(fd); }
int main(int argc, char *argv[]) { int c; static struct option long_options[] = { { "help", no_argument, 0, 'h'}, { "file", required_argument, 0, 'f'}, { "layout", required_argument, 0, 'l'}, { "bsize", required_argument, 0, 'b'}, { "chunk", required_argument, 0, 'c'}, { "blockNumber", required_argument, 0, 'n'}, { 0, 0, 0, 0} }; // Get utility name utility_name = basename(argv[0]); rozofs_layout_initialize(); while (1) { int option_index = 0; c = getopt_long(argc, argv, "hH:f:l:b:c:n:", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': usage(); exit(EXIT_SUCCESS); break; break; case 'f': filename[nb_file++] = optarg; break; case 'l': { int ret; ret = sscanf(optarg,"%d", &layout); if (ret <= 0) { fprintf(stderr, "dataReader failed. Bad layout: %s %s\n", optarg, strerror(errno)); exit(EXIT_FAILURE); } } break; case 'c': { int ret; ret = sscanf(optarg,"%d", &firstBlock); if (ret <= 0) { fprintf(stderr, "dataReader failed. Bad chunk number: %s %s\n", optarg, strerror(errno)); exit(EXIT_FAILURE); } } break; case 'n': { int ret; ret = sscanf(optarg,"%d", &block_number); if (ret < 0) { fprintf(stderr, "dataReader failed. Bad block number: %s %s\n", optarg, strerror(errno)); exit(EXIT_FAILURE); } } break; case 'b': { int ret; ret = sscanf(optarg,"%d", &bsize); if (ret < 0) { fprintf(stderr, "dataReader failed. Bad block size: %s %s\n", optarg, strerror(errno)); exit(EXIT_FAILURE); } } break; case '?': usage(); exit(EXIT_SUCCESS); break; default: usage(); exit(EXIT_FAILURE); break; } } openlog("dataReader", LOG_PID, LOG_DAEMON); /* ** Check parameter consistency */ if (nb_file == 0){ fprintf(stderr, "dataReader failed. Missing --file option.\n"); exit(EXIT_FAILURE); } bbytes = ROZOFS_BSIZE_BYTES(bsize); if (bbytes < 0) { fprintf(stderr, "bad block size: %d\n", bsize); exit(EXIT_FAILURE); } firstBlock *= ROZOFS_STORAGE_NB_BLOCK_PER_CHUNK(bsize); // Start rebuild storage if (read_data_file() != 0) goto error; exit(EXIT_SUCCESS); error: exit(EXIT_FAILURE); }