Пример #1
0
        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();
        }
Пример #2
0
        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);
        }
Пример #3
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();
            }
        }
Пример #4
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)
                {
                    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();
            }
        }