void nfs_client_impl::end_copy( ::dsn::error_code err, const copy_response& resp, void* context) { //dinfo("*** call RPC_NFS_COPY end, return (%d, %d) with %s", resp.offset, resp.size, err.to_string()); dsn::ref_ptr<copy_request_ex> reqc; reqc = (copy_request_ex*)context; reqc->release_ref(); continue_copy(1); if (err == ERR_OK) { err = resp.error; } if (err != ::dsn::ERR_OK) { handle_completion(reqc->file_ctx->user_req, err); return; } reqc->response = resp; reqc->response.error.end_tracking(); // always ERR_OK reqc->is_ready_for_write = true; auto& fc = reqc->file_ctx; // check write availability { zauto_lock l(fc->user_req->user_req_lock); if (fc->current_write_index != reqc->index - 1) return; } // check readies for local writes { zauto_lock l(fc->user_req->user_req_lock); for (int i = reqc->index; i < (int)(fc->copy_requests.size()); i++) { if (fc->copy_requests[i]->is_ready_for_write) { fc->current_write_index++; { zauto_lock l(_local_writes_lock); _local_writes.push(fc->copy_requests[i]); } } else break; } } continue_write(); }
void nfs_client_impl::end_get_file_size( ::dsn::error_code err, const ::dsn::service::get_file_size_response& resp, void* context) { user_request* ureq = (user_request*)context; if (err != ::dsn::ERR_OK) { derror("remote copy request failed"); ureq->nfs_task->enqueue(err, 0); delete ureq; return; } err = resp.error; if (err != ::dsn::ERR_OK) { derror("remote copy request failed"); ureq->nfs_task->enqueue(err, 0); delete ureq; return; } for (size_t i = 0; i < resp.size_list.size(); i++) // file list { file_context *filec; uint64_t size = resp.size_list[i]; filec = new file_context(ureq, resp.file_list[i], resp.size_list[i]); ureq->file_context_map.insert(std::pair<std::string, file_context*>( utils::filesystem::path_combine(ureq->file_size_req.dst_dir, resp.file_list[i]), filec )); //dinfo("this file size is %d, name is %s", size, resp.file_list[i].c_str()); // new all the copy requests uint64_t req_offset = 0; uint32_t req_size; if (size > _opts.nfs_copy_block_bytes) req_size = _opts.nfs_copy_block_bytes; else req_size = static_cast<uint32_t>(size); int idx = 0; for (;;) // send one file with multi-round rpc { auto req = dsn::ref_ptr<copy_request_ex>(new copy_request_ex(filec, idx++)); filec->copy_requests.push_back(req); { zauto_lock l(_copy_requests_lock); _copy_requests.push(req); } req->copy_req.source = ureq->file_size_req.source; req->copy_req.file_name = resp.file_list[i]; req->copy_req.offset = req_offset; req->copy_req.size = req_size; req->copy_req.dst_dir = ureq->file_size_req.dst_dir; req->copy_req.source_dir = ureq->file_size_req.source_dir; req->copy_req.overwrite = ureq->file_size_req.overwrite; req->copy_req.is_last = (size <= req_size); req_offset += req_size; size -= req_size; if (size <= 0) { dassert(size == 0, "last request must read exactly the remaing size of the file"); break; } if (size > _opts.nfs_copy_block_bytes) req_size = _opts.nfs_copy_block_bytes; else req_size = static_cast<uint32_t>(size); } } continue_copy(0); }
void nfs_client_impl::handle_completion(user_request *req, error_code err) { { zauto_lock l(req->user_req_lock); if (req->is_finished) return; req->is_finished = true; } for (auto& f : req->file_context_map) { for (auto& rc : f.second->copy_requests) { ::dsn::task_ptr ctask, wtask; { zauto_lock l(rc->lock); rc->is_valid = false; ctask = rc->remote_copy_task; wtask = rc->local_write_task; rc->remote_copy_task = nullptr; rc->local_write_task = nullptr; } if (err != ERR_OK) { if (ctask != nullptr) { if (ctask->cancel(true)) { _concurrent_copy_request_count--; rc->release_ref(); } } if (wtask != nullptr) { if (wtask->cancel(true)) { _concurrent_local_write_count--; } } } } if (f.second->file) { auto err2 = dsn_file_close(f.second->file); dassert(err2 == ERR_OK, "dsn_file_close failed, err = %s", dsn_error_to_string(err2)); f.second->file = nullptr; if (f.second->finished_segments != (int)f.second->copy_requests.size()) { ::remove((f.second->user_req->file_size_req.dst_dir + f.second->file_name).c_str()); } f.second->copy_requests.clear(); } delete f.second; } req->file_context_map.clear(); req->nfs_task->enqueue(err, 0); delete req; // clear out all canceled requests if (err != ERR_OK) { continue_copy(0); continue_write(); } }
void nfs_client_impl::handle_completion(user_request *req, error_code err) { { zauto_lock l(req->user_req_lock); if (req->is_finished) return; req->is_finished = true; } for (auto& f : req->file_context_map) { for (auto& rc : f.second->copy_requests) { task_ptr ctask, wtask; { zauto_lock l(rc->lock); rc->is_valid = false; ctask = rc->remote_copy_task; wtask = rc->local_write_task; rc->remote_copy_task = nullptr; rc->local_write_task = nullptr; } if (err != ERR_OK) { if (ctask != nullptr) { if (ctask->cancel(true)) { _concurrent_copy_request_count--; rc->release_ref(); } } if (wtask != nullptr) { if (wtask->cancel(true)) { _concurrent_local_write_count--; } } } } if (f.second->file) { file::close(f.second->file); f.second->file = static_cast<handle_t>(0); if (f.second->finished_segments != (int)f.second->copy_requests.size()) { boost::filesystem::remove(f.second->user_req->file_size_req.dst_dir + f.second->file_name); } } delete f.second; } req->file_context_map.clear(); req->nfs_task->enqueue(err, 0, req->nfs_task->node()); delete req; // clear out all canceled requests if (err != ERR_OK) { continue_copy(0); continue_write(); } }