Skip to content

Instantly share code, notes, and snippets.

@hirokuma
Created February 24, 2019 05:16
Show Gist options
  • Save hirokuma/b0b5a9a92930f5c9a91dbcab207c382b to your computer and use it in GitHub Desktop.
Save hirokuma/b0b5a9a92930f5c9a91dbcab207c382b to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include "lmdb.h"
#define DBDIR "./testdb"
#define DBNAME "name"
static MDB_env *env;
static struct db_t {
MDB_txn *txn;
MDB_dbi dbi;
} dbr, dbw;
static int tid(void)
{
return (int)syscall(SYS_gettid);
}
static void db_open(struct db_t *pdb, unsigned int flags)
{
int rc;
MDB_envinfo stat;
if (mdb_env_info(env, &stat) == 0) {
fprintf(stderr, " last txnid=%lu\n", stat.me_last_txnid);
}
fprintf(stderr, " -->db_open(tid=%d)\n", tid());
rc = mdb_txn_begin(env, NULL, flags, &pdb->txn);
if (rc) {
fprintf(stderr, "fail: mdb_txn_begin(%s)\n", mdb_strerror(rc));
goto LABEL_EXIT2;
}
rc = mdb_dbi_open(pdb->txn, DBNAME, 0, &pdb->dbi);
if (rc) {
fprintf(stderr, "fail: mdb_dbi_open(%s)\n", mdb_strerror(rc));
mdb_txn_abort(pdb->txn);
goto LABEL_EXIT2;
}
fprintf(stderr, " -->db_open exit(tid=%d)\n", tid());
LABEL_EXIT2:
return;
}
static void db_w(void)
{
MDB_val key, data;
fprintf(stderr, " -->db_w(tid=%d)\n", tid());
int code = 5;
int slp = 30;
key.mv_size = sizeof(code);
key.mv_data = &code;
data.mv_size = sizeof(slp);
data.mv_data = &slp;
int rc = mdb_put(dbw.txn, dbw.dbi, &key, &data, 0);
if (rc == 0) {
fprintf(stderr, " -->txn commit(tid=%d)\n", tid());
mdb_txn_commit(dbw.txn);
} else {
fprintf(stderr, "fail: mdb_put(%s)\n", mdb_strerror(rc));
mdb_txn_abort(dbw.txn);
}
fprintf(stderr, " -->db_w exit(tid=%d)\n", tid());
}
static void *thread_func_r(void *pArg)
{
//1. open RDONLY
fprintf(stderr, "1. open RDONLY(tid=%d)\n", (int)syscall(SYS_gettid));
db_open(&dbr, MDB_RDONLY);
sleep(2);
//3. aobrt RDONLY
fprintf(stderr, "3. abort RDONLY(tid=%d)\n", (int)syscall(SYS_gettid));
mdb_txn_abort(dbr.txn);
//4. open NORMAL
fprintf(stderr, "4. open NORMAL(tid=%d)\n", (int)syscall(SYS_gettid));
db_open(&dbr, 0);
fprintf(stderr, "txn abort(tid=%d)\n", (int)syscall(SYS_gettid));
mdb_txn_abort(dbr.txn);
return NULL;
}
static void *thread_func_w(void *pArg)
{
//2. open NORMAL
fprintf(stderr, "2. open NORMAL(tid=%d)\n", (int)syscall(SYS_gettid));
db_open(&dbw, 0);
sleep(2);
//5. put
fprintf(stderr, "5. put(tid=%d)\n", (int)syscall(SYS_gettid));
db_w();
return NULL;
}
int main(void)
{
int rc;
MDB_txn *txn;
MDB_dbi dbi;
mkdir(DBDIR, 0755);
rc = mdb_env_create(&env);
if (rc) {
fprintf(stderr, "fail: mdb_env_create(%s)\n", mdb_strerror(rc));
}
rc = mdb_env_set_maxdbs(env, 1);
if (rc) {
fprintf(stderr, "fail: mdb_env_set_maxdbs(%s)\n", mdb_strerror(rc));
}
rc = mdb_env_open(env, DBDIR, MDB_FIXEDMAP, 0664);
if (rc) {
fprintf(stderr, "fail: mdb_env_open(%s)\n", mdb_strerror(rc));
goto LABEL_EXIT1;
}
rc = mdb_txn_begin(env, NULL, 0, &txn);
if (rc) {
fprintf(stderr, "fail: mdb_txn_begin(%s)\n", mdb_strerror(rc));
goto LABEL_EXIT1;
}
rc = mdb_dbi_open(txn, DBNAME, MDB_CREATE, &dbi);
if (rc) {
fprintf(stderr, "fail: mdb_dbi_open(%s)\n", mdb_strerror(rc));
mdb_txn_abort(txn);
goto LABEL_EXIT1;
}
mdb_txn_commit(txn);
pthread_t th1;
pthread_create(&th1, NULL, &thread_func_r, (void *)1);
sleep(1);
pthread_t th2;
pthread_create(&th2, NULL, &thread_func_w, (void *)2);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
LABEL_EXIT1:
mdb_env_close(env);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment