Пример #1
0
        void nfs_service_impl::close_file() // release out-of-date file handle
        {
            zauto_lock l(_handles_map_lock);

            for (auto it = _handles_map.begin(); it != _handles_map.end();)
            {
                auto fptr = it->second;

                // not used and expired
                if (fptr->file_access_count == 0 
                    && dsn_now_ms() - fptr->last_access_time > _opts.file_close_expire_time_ms)
                {
                    dinfo("nfs: close file handle %s", it->first.c_str());
                    it = _handles_map.erase(it);

                    ::dsn::error_code err = dsn_file_close(fptr->file_handle);
                    dassert(err == ERR_OK, "dsn_file_close failed, err = %s", err.to_string());
                    delete fptr;
                }
                else
                    it++;
            }
        }
Пример #2
0
        void nfs_client_impl::local_write_callback(error_code err, size_t sz, dsn::ref_ptr<copy_request_ex> reqc)
        {
            //dassert(reqc->local_write_task == task::get_current_task(), "");
            --_concurrent_local_write_count;

            // clear all content to release memory quickly
            reqc->response.file_content = blob();

            continue_write();

            bool completed = false;
            if (err != ERR_OK)
            {
                completed = true;
            }
            else
            {
                zauto_lock l(reqc->file_ctx->user_req->user_req_lock);
                if (++reqc->file_ctx->finished_segments == (int)reqc->file_ctx->copy_requests.size())
                {
                    auto err = dsn_file_close(reqc->file_ctx->file);
                    dassert(err == ERR_OK, "dsn_file_close failed, err = %s", dsn_error_to_string(err));
                    reqc->file_ctx->file = static_cast<dsn_handle_t>(0);
                    reqc->file_ctx->copy_requests.clear();

                    if (++reqc->file_ctx->user_req->finished_files == (int)reqc->file_ctx->user_req->file_context_map.size())
                    {
                        completed = true;
                    }
                }
            }

            if (completed)
            {   
                handle_completion(reqc->file_ctx->user_req, err);
            }
        }
Пример #3
0
void aio_testcase(uint64_t block_size, uint64_t total_size_mb, size_t concurrency, bool is_write, bool random_offset)
{
    std::unique_ptr<char[]> buffer(new char[block_size]);
    std::atomic_uint remain_concurrency;
    remain_concurrency = concurrency;
    if (is_write && utils::filesystem::file_exists("temp"))
    {
        utils::filesystem::remove_path("temp");
        dassert(!utils::filesystem::file_exists("temp"), "");
    }
    auto file_handle = dsn_file_open("temp", O_CREAT | O_RDWR, 0666);
    auto total_size_bytes = total_size_mb * 1024 * 1024;
    auto tic = std::chrono::steady_clock::now();

    for (int bytes_written = 0; bytes_written < total_size_bytes; )
    {
        while (true)
        {
            if (remain_concurrency.fetch_sub(1, std::memory_order_acquire) <= 0)
            {
                remain_concurrency.fetch_add(1, std::memory_order_relaxed);
            }
            else
            {
                break;
            }
        }
        auto cb = [&](error_code ec, int sz)
        {
            dassert(ec == ERR_OK && uint64_t(sz) == block_size,
                "ec = %s, sz = %d, block_size = %" PRId64 "",
                ec.to_string(), sz, block_size
                );
            remain_concurrency.fetch_add(1, std::memory_order_relaxed);
        };
        auto offset = random_offset ? dsn_random64(0, total_size_bytes - block_size) : bytes_written;
        if (is_write)
        {
            file::write(file_handle, buffer.get(), block_size, offset, LPC_AIO_TEST, nullptr, cb);
        }
        else
        {
            file::read(file_handle, buffer.get(), block_size, offset, LPC_AIO_TEST, nullptr, cb);
        }

        bytes_written += block_size;
    }
    while (remain_concurrency != concurrency)
    {
        ;
    }
    dsn_file_flush(file_handle);
    auto toc = std::chrono::steady_clock::now();
    auto c*k = dsn_file_close(file_handle);
    EXPECT_EQ(c*k, ERR_OK);

    std::cout << "is_write = " << is_write
        << " random_offset = " << random_offset
        << " block_size = " << block_size
        << " concurrency = " << concurrency
        << " throughput = " << double(total_size_mb) * 1000000 / std::chrono::duration_cast<std::chrono::microseconds>(toc - tic).count() << " mB/s" << std::endl;
}
Пример #4
0
void aio_testcase(uint64_t block_size, size_t concurrency, bool is_write, bool shared)
{
    std::unique_ptr<char[]> buffer(new char[block_size]);
    std::vector<dsn_handle_t> files;
    files.resize(concurrency);

    int flag;
    if (is_write)
    {
        flag = O_CREAT | O_RDWR;
        if (shared)
        {
            if (utils::filesystem::file_exists("temp"))
                utils::filesystem::remove_path("temp");
        }
        else
        {
            for (int i = 0; i < concurrency; i++)
            {
                std::stringstream ss;
                ss << "temp." << i;
                auto file = ss.str();
                if (utils::filesystem::file_exists(file))
                    utils::filesystem::remove_path(file);
            }
        }
    }
    else
    {
        flag = O_RDWR;
    }

    if (shared)
    {
        auto file_handle = dsn_file_open("temp", flag, 0666);
        EXPECT_TRUE(file_handle != nullptr);
        for (int i = 0; i < concurrency; i++)
            files[i] = file_handle;
    }
    else
    {
        for (int i = 0; i < concurrency; i++)
        {
            std::stringstream ss;
            ss << "temp." << i;
            auto file = ss.str();
            auto file_handle = dsn_file_open(file.c_str(), flag, 0666);
            EXPECT_TRUE(file_handle != nullptr);
            files[i] = file_handle;
        }
    }
    
    std::atomic<uint64_t> io_count(0);
    std::atomic<uint64_t> cb_flying_count(0);
    volatile bool exit = false;
    std::function<void(int)> cb;
    std::vector<uint64_t> offsets;
    offsets.resize(concurrency);
    
    cb = [&](int index)
    {
        if (!exit)
        {
            auto ioc = io_count++;
            uint64_t offset;
            if (!shared)
            {
                offset = offsets[index];
                offsets[index] += block_size;
            }
            else
            {
                offset = ioc * block_size;
            }

            cb_flying_count++;
            if (is_write)
            {
                file::write(files[index], buffer.get(), (int)block_size, offset,
                    LPC_AIO_TEST, nullptr, [idx = index, &cb, &cb_flying_count](::dsn::error_code code, size_t sz) 
                    {                        
                        if (ERR_OK == code)
                            cb(idx);
                        cb_flying_count--;
                    });                
            }
            else
            {
                file::read(files[index], buffer.get(), (int)block_size, offset,
                    LPC_AIO_TEST, nullptr, [idx = index, &cb, &cb_flying_count](::dsn::error_code code, size_t sz)
                    {                        
                        if (ERR_OK == code)
                            cb(idx);
                        cb_flying_count--;
                    });
            }
        }
    };

    // start
    auto tic = std::chrono::steady_clock::now();
    for (int i = 0; i < concurrency; i++)
    {
        offsets[i] = 0;
        cb(i);
    }

    // run for seconds
    std::this_thread::sleep_for(std::chrono::seconds(10));
    auto ioc = io_count.load();
    auto bytes = ioc * block_size;    
    auto toc = std::chrono::steady_clock::now();
    
    std::cout << "is_write = " << is_write        
        << ", block_size = " << block_size
        << ", shared = " << shared
        << ", concurrency = " << concurrency
        << ", iops = " << (double)ioc / (double)std::chrono::duration_cast<std::chrono::microseconds>(toc - tic).count() * 1000000.0 << " #/s"
        << ", throughput = " << (double)bytes / std::chrono::duration_cast<std::chrono::microseconds>(toc - tic).count() << " mB/s"
        << ", avg_latency = " << (double)std::chrono::duration_cast<std::chrono::microseconds>(toc - tic).count() / (double)(ioc / concurrency) << " us"
        << std::endl;

    // safe exit
    exit = true;

    while (cb_flying_count.load() > 0)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    if (shared)
    {
        dsn_file_flush(files[0]);
        auto c*k = dsn_file_close(files[0]);
        EXPECT_EQ(c*k, ERR_OK);
    }
    else
    {
        for (auto& f : files)
        {
            dsn_file_flush(f);
            auto c*k = dsn_file_close(f);
            EXPECT_EQ(c*k, ERR_OK);
        }
    }
}
 meta_state_service_simple::~meta_state_service_simple()
 {
     dsn_file_close(_log);
 }
Пример #6
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();
            }
        }