创建

可以创建带目录和不带目录的,都会产生主题数据文件和锁(lock)文件。锁文件可以删除,因为下次打开的时候会自动创建。

创建 env 之后,要先设置 mapsize 再创建打开文件;mapsize 可以设置很大,如果设置的太小,会导致加数据或提交时出现 MDB_MAP_FULL 错误。不同担心 mapsize 设置很大时,没开始写数据内存就爆,或写出去的数据文件会特别大,不会的,内存和文件只和你喂给它数据多少有关。

inline void check(int code)
{
    if (code != MDB_SUCCESS)
    {
        auto msg = mdb_strerror(code);
        throw std::runtime_error(msg);
    }
}

void create(const fs::path& lmdbFilename, bool subdir)
{
    MDB_env *env = nullptr;
    check(mdb_env_create(&env));
    check(mdb_env_set_mapsize(env, 1099511627776ul)); // 1 TB

    check(mdb_env_open(env, lmdbFilename.u8string().c_str(), subdir ? 0 : MDB_NOSUBDIR, 0664));

    MDB_txn *txn = nullptr;
    check(mdb_txn_begin(env, nullptr, 0, &txn));

    MDB_dbi dbi = 0;
    check(mdb_dbi_open(txn, nullptr, 0, &dbi));

    std::string str(u8"test");
    std::vector<uint8_t> data(128, 0);

    MDB_val key{0};
    key.mv_data = (void*)str.data();
    key.mv_size = str.size();

    MDB_val val{0};
    val.mv_data = (void*)data.data();
    val.mv_size = data.size();

    check(mdb_put(txn, dbi, &key, &val, 0));

    check(mdb_txn_commit(txn));
    mdb_dbi_close(env, dbi);

    mdb_env_close(env);
}

读取

打开文件时建议加上 MDB_FIXEDMAP,加上读取时要相对快很多。

void read(const fs::path& lmdbFilename, bool subdir)
{
    MDB_env *env = nullptr;
    check(mdb_env_create(&env));
    check(mdb_env_set_mapsize(env, 1099511627776ul)); // 1 TB

    int flags = MDB_FIXEDMAP | MDB_RDONLY | (subdir ? 0 : MDB_NOSUBDIR);
    check(mdb_env_open(env, lmdbFilename.u8string().c_str(), flags, 0664));

    MDB_txn *txn = nullptr;
    check(mdb_txn_begin(env, nullptr, flags, &txn));

    MDB_dbi dbi = 0;
    check(mdb_dbi_open(txn, nullptr, 0, &dbi));

    MDB_cursor *cursor = nullptr;
    check(mdb_cursor_open(txn, dbi, &cursor));


    MDB_val key{0};
    MDB_val val{0};
    int ret = MDB_SUCCESS;
    while ((ret = mdb_cursor_get(cursor, &key, &val, MDB_NEXT)) != MDB_NOTFOUND)
    {
        check(ret);

        std::string str((const char*)key.mv_data, (const char*)key.mv_data + key.mv_size);
        std::vector<uint8_t> data((const uint8_t*)val.mv_data, (const uint8_t*)val.mv_data + val.mv_size);
        cout << str << endl;
    }

    mdb_txn_abort(txn);
    mdb_dbi_close(env, dbi);

    mdb_env_close(env);
}

发表回复

您的电子邮箱地址不会被公开。