int LMDBEngine::Del(const Slice& key) { LMDBContext& holder = m_ctx_local.GetValue(); MDB_txn *txn = holder.readonly_txn; if (NULL == txn || holder.batch_write == 0) { MDB_val k; k.mv_data = const_cast<char*>(key.data()); k.mv_size = key.size(); mdb_txn_begin(m_env, NULL, 0, &txn); mdb_del(txn, m_dbi, &k, NULL); mdb_txn_commit(txn); return 0; } DelOperation* op = new DelOperation; op->key.assign((const char*) key.data(), key.size()); m_write_queue.Push(op); if (holder.batch_write == 0) { CheckPointOperation* ck = new CheckPointOperation(holder.cond); m_write_queue.Push(ck); NotifyBackgroundThread(); ck->Wait(); DELETE(ck); return 0; } return 0; }
int LMDBEngine::Put(const Slice& key, const Slice& value, const Options& options) { LMDBContext& holder = m_ctx_local.GetValue(); MDB_txn *txn = holder.readonly_txn; if (NULL == txn || holder.batch_write == 0) { MDB_val k, v; k.mv_data = const_cast<char*>(key.data()); k.mv_size = key.size(); v.mv_data = const_cast<char*>(value.data()); v.mv_size = value.size(); CHECK_OP(mdb_txn_begin(m_env, NULL, 0, &txn)); CHECK_OP(mdb_put(txn, m_dbi, &k, &v, 0)); CHECK_OP(mdb_txn_commit(txn)); return 0; } PutOperation* op = new PutOperation; op->key.assign((const char*) key.data(), key.size()); op->value.assign((const char*) value.data(), value.size()); m_write_queue.Push(op); if (holder.batch_write == 0) { CheckPointOperation* ck = new CheckPointOperation(holder.cond); m_write_queue.Push(ck); NotifyBackgroundThread(); ck->Wait(); DELETE(ck); return 0; } return 0; }
int LMDBEngine::DiscardBatchWrite() { LMDBContext& holder = m_ctx_local.GetValue(); holder.batch_write--; if (holder.batch_write == 0) { CheckPointOperation* ck = new CheckPointOperation(holder.cond); m_write_queue.Push(ck); NotifyBackgroundThread(); ck->Wait(); DELETE(ck); } return 0; }
void LMDBEngine::Run() { while (m_running) { MDB_txn* txn; int rc = mdb_txn_begin(m_env, NULL, 0, &txn); if (rc != 0) { Thread::Sleep(10, MILLIS); continue; } WriteOperation* op = NULL; int count = 0; while (m_write_queue.Pop(op)) { switch (op->type) { case PUT_OP: { PutOperation* pop = (PutOperation*) op; MDB_val k, v; k.mv_data = const_cast<char*>(pop->key.data()); k.mv_size = pop->key.size(); v.mv_data = const_cast<char*>(pop->value.data()); v.mv_size = pop->value.size(); int rc = mdb_put(txn, m_dbi, &k, &v, 0); if(0 != rc) { ERROR_LOG("Write error:%s", mdb_strerror(rc)); } DELETE(op); break; } case DEL_OP: { DelOperation* pop = (DelOperation*) op; MDB_val k; k.mv_data = const_cast<char*>(pop->key.data()); k.mv_size = pop->key.size(); mdb_del(txn, m_dbi, &k, NULL); DELETE(op); break; } case CKP_OP: { mdb_txn_commit(txn); txn = NULL; CheckPointOperation* cop = (CheckPointOperation*) op; cop->Notify(); break; } default: { break; } } count++; if (count == m_cfg.batch_commit_watermark || NULL == txn) { break; } } if (NULL != txn) { mdb_txn_commit(txn); } if (count == 0) { m_queue_cond.Lock(); m_queue_cond.Wait(5); m_queue_cond.Unlock(); } } }