google / leveldb

LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.
BSD 3-Clause "New" or "Revised" License
36.45k stars 7.81k forks source link

leveldb::port::CondVar::Wait for a long time #444

Open egmkang opened 7 years ago

egmkang commented 7 years ago

thread 1:

(gdb) bt
#0  0x00007f8857f116d5 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x000000000050953d in leveldb::port::CondVar::Wait() ()
#2  0x00000000004ef8f6 in leveldb::DBImpl::Write(leveldb::WriteOptions const&, leveldb::WriteBatch*) ()
#3  0x00000000004ec98a in leveldb::DB::Put(leveldb::WriteOptions const&, leveldb::Slice const&, leveldb::Slice const&) ()
#4  0x00000000004ec9d9 in leveldb::DBImpl::Put(leveldb::WriteOptions const&, leveldb::Slice const&, leveldb::Slice const&) ()
#5  0x00000000004a2355 in storage::Flush () at /home/zhanjian/server/RecordServer/storage.cpp:67
#6  0x0000000000492e64 in Server::OnHourChanged (this=0x7f8856a84000) at /home/zhanjian/server/RecordServer/server.cpp:141
#7  0x00000000004927d8 in Server::OnSecondsChanged (this=0x7f8856a84000) at /home/zhanjian/server/RecordServer/server.cpp:117
#8  0x0000000000421167 in Server::Loop (this=0x7f8856a84000) at /home/zhanjian/server/RecordServer/message_loop.cpp:208
#9  0x00000000004092f8 in main () at /home/zhanjian/server/RecordServer/main.cpp:8

thread 2:

(gdb) bt
#0  0x00007f8857f116d5 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x000000000050953d in leveldb::port::CondVar::Wait() ()
#2  0x00000000004ee920 in leveldb::DBImpl::MakeRoomForWrite(bool) ()
#3  0x00000000004ef96b in leveldb::DBImpl::Write(leveldb::WriteOptions const&, leveldb::WriteBatch*) ()
#4  0x00000000004ec98a in leveldb::DB::Put(leveldb::WriteOptions const&, leveldb::Slice const&, leveldb::Slice const&) ()
#5  0x00000000004ec9d9 in leveldb::DBImpl::Put(leveldb::WriteOptions const&, leveldb::Slice const&, leveldb::Slice const&) ()
#6  0x00000000004a1ea8 in storage::Set (key="ReportID:1703508535200012848", 
    value="\324\003\000\001u \000\000\367H\n\302\v\b\202\200\325\372\377\354\373\317\024\020\244\350\003\030\225\034\"W\nM\r|\025\231\000\020\034\060>8\003P\001h\000z\f\332\353\023\334\353\023\335\353\023\336\353\023\202\001*\270\261\a\201\357\001\220 \220 \352\t\246\006\000\000\000\000\003\000\000\000\000\000T\000F\224\001\000\000\002\000\366(\210\001\005\020\001 \201\357\001(\003\"P\nF\r^ǘ\000\020\031\060-8\003P\002hZz\006\262\321\a\257\321\a\202\001)\352\353\003?\001\237\025\237\025\375\005\353\aS\000F\000\000\"jO\000\003R\000\361\025\002 ?\001(\003\"U\nK\r{\025\231\000\020\023\060,8\002P\002h\333\001z\t\241\215\006\320"...) at /home/zhanjian/server/RecordServer/storage.cpp:41
#7  0x000000000040f7ad in ProcessSaveReport (entry=...) at /home/zhanjian/server/RecordServer/message_handler.cpp:247
#8  0x0000000000420f89 in NameThread::Loop (this=0x7f8856a86200) at /home/zhanjian/server/RecordServer/message_loop.cpp:180
#9  0x00000000004a1923 in boost::_mfi::mf0<void, NameThread>::operator() (this=0x7f8856b6e7b8, p=0x7f8856a86200) at /home/zhanjian/server/deps/boost_1_58/boost/bind/mem_fn_template.hpp:49
#10 0x00000000004a1610 in boost::_bi::list1<boost::_bi::value<NameThread*> >::operator()<boost::_mfi::mf0<void, NameThread>, boost::_bi::list0> (this=0x7f8856b6e7c8, f=..., a=...)
    at /home/zhanjian/server/deps/boost_1_58/boost/bind/bind.hpp:253
#11 0x00000000004a1391 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, NameThread>, boost::_bi::list1<boost::_bi::value<NameThread*> > >::operator() (this=0x7f8856b6e7b8)
    at /home/zhanjian/server/deps/boost_1_58/boost/bind/bind_template.hpp:20
#12 0x00000000004a113e in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, NameThread>, boost::_bi::list1<boost::_bi::value<NameThread*> > > >::run (this=0x7f8856b6e600)
    at /home/zhanjian/server/deps/boost_1_58/boost/thread/detail/thread.hpp:116
#13 0x00000000004e6869 in thread_proxy ()
#14 0x00007f8857f0ddc5 in start_thread () from /lib64/libpthread.so.0
#15 0x00007f885721373d in clone () from /lib64/libc.so.6

the two threads are waiting for a long time. how can i solve this problem? leveldb's diectionary size is 4.6M.

egmkang commented 7 years ago

here is the storage wrapper codes:

#include "storage.h"
#include <system.h>
#include <leveldb/db.h>
#include <leveldb/cache.h>
#include <logger.h>

const int32_t kDBCacheSize = 100 * 1048576;  //100MB
leveldb::DB* db = NULL;
leveldb::Options options;
const char* db_name = "./db";

namespace storage {

void Init() {
  options.create_if_missing = true;
  //options.compression = leveldb::kNoCompression;
  if (!options.block_cache)
    options.block_cache = leveldb::NewLRUCache(kDBCacheSize);
  leveldb::Status status = leveldb::DB::Open(options, db_name, &db);
  if (!status.ok()) {
    ERROR_LOG(logger)("Init LevelDB Fail");
  } else {
    db->CompactRange(NULL, NULL);
    TRACE_LOG(logger)("Init LevelDB Success");
  }
}

void Set(const std::string& key, const std::string& value) {
  if (db) {
    INFO_LOG(logger)("LevelDB Put:%s", key.c_str());
    leveldb::Status s = db->Put(leveldb::WriteOptions(), key, value);
    DEBUG_LOG(logger)("LevelDB Put:%s, Length:%lu, Success:%d", key.c_str(), value.size(), s.ok());
  }
}

std::string Get(const std::string& key) {
  std::string value;
  INFO_LOG(logger)("LevelDB Get:%s", key.c_str());
  leveldb::Status s = db->Get(leveldb::ReadOptions(), key, &value);
  if (!s.ok()) value.clear();
  DEBUG_LOG(logger)("LevelDB Get:%s, Success:%d", key.c_str(), s.ok());
  return value;
}

void Delete(const std::string& key) {
  if (db) {
    INFO_LOG(logger)("LevelDB Delete:%s", key.c_str());
    leveldb::Status s = db->Delete(leveldb::WriteOptions(), key);
    DEBUG_LOG(logger)("LevelDB Delete:%s, Success:%d", key.c_str(), s.ok());
  }
}

void Flush() {
  if (db) {
    leveldb::WriteOptions write_options;
    write_options.sync = true;
    db->Put(write_options, "FLUSH", "FLUSH");
    DEBUG_LOG(logger)("LevelDB Flush");
  }
}

}