{"id":261378,"date":"2015-07-14T12:48:02","date_gmt":"2015-07-14T08:48:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=261378"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=261378","title":{"rendered":"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 LevelDB"},"content":{"rendered":"<p>     \t\u0421\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0435\u0439, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0438 \u043a\u043e\u043b\u043b\u0435\u0433\u0438 \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u0433\u043e key-value \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 SQLite, MemcacheDB, Redis \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044f \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a LevelDB, Sophia, HamsterDB \u0438 \u0442.\u0434.<\/p>\n<p>  \u042f \u0440\u0430\u0437\u0431\u0438\u043b \u0441\u0442\u0430\u0442\u044c\u044e \u043d\u0430 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438:  <\/p>\n<ol>\n<li><a href=\"#1\">\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 api LevelDB;<\/a><\/li>\n<li><a href=\"#2\">\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 LevelDB, \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u044f\u0434\u043e\u0432.<\/a><\/li>\n<\/ol>\n<p>  <a name=\"habracut\"><\/a><\/p>\n<h4><b><a name=\"1\"><\/a> LevelDB \u0438 \u0435\u0433\u043e API<\/b><\/h4>\n<p>  \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 LevelDB:  <\/p>\n<ul>\n<li>\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0442\u0438\u043f\u0430 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435;<\/li>\n<li>\u043a\u043b\u044e\u0447 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0430\u0439\u0442;<\/li>\n<li>\u0434\u0430\u043d\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0435\u043d\u043d\u043e, \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c;<\/li>\n<li>\u043f\u0440\u044f\u043c\u043e\u0439 \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u0445\u043e\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li>\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435;<\/li>\n<li>\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u043d\u0438\u043c\u043a\u043e\u0432;<\/li>\n<li>\u0441\u0436\u0430\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/code.google.com\/p\/snappy\/\">Snappy<\/a>.<\/li>\n<\/ul>\n<h5><b>\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435<\/b><\/h5>\n<p>  \u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435:  <\/p>\n<pre><code class=\"cpp\">#include &lt;assert&gt; #include &quot;leveldb\/db.h&quot;  leveldb::DB* db; leveldb::Options options; options.create_if_missing = true; leveldb::Status status = leveldb::DB::Open(options, &quot;\/tmp\/testdb&quot;, &db); assert(status.ok()); <\/code><\/pre>\n<p>  \u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435:  <\/p>\n<pre><code class=\"cpp\">delete db; <\/code><\/pre>\n<p>  <b>\u041e\u043f\u0446\u0438\u0438:<\/b>  <\/p>\n<table>\n<tr>\n<th>\u0418\u043c\u044f<\/th>\n<th>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/th>\n<th>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e<\/th>\n<\/tr>\n<tr>\n<td>comparator<\/td>\n<td>\u043a\u043e\u043c\u043f\u0430\u0440\u0430\u0442\u043e\u0440 \u0437\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043a\u043b\u044e\u0447\u0435\u0439<\/td>\n<td>BytewiseComparator, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f <a href=\"http:\/\/www.cplusplus.com\/reference\/cstring\/memcmp\/\">memcmp<\/a><\/td>\n<\/tr>\n<tr>\n<td>create_if_missing<\/td>\n<td>\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u0443, \u0435\u0441\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442<\/td>\n<td>false<\/td>\n<\/tr>\n<tr>\n<td>error_if_exists<\/td>\n<td>\u0432\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443, \u0435\u0441\u043b\u0438 \u0431\u0430\u0437\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442<\/td>\n<td>false<\/td>\n<\/tr>\n<tr>\n<td>paranoid_checks<\/td>\n<td>\u0430\u0433\u0440\u0435\u0441\u0441\u0438\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u0431\u0430\u0437\u044b<\/td>\n<td>false<\/td>\n<\/tr>\n<tr>\n<td>env<\/td>\n<td>\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u0432\u043e\u0434\u0430\/\u0432\u044b\u0432\u043e\u0434\u0430<\/td>\n<td>Env::Default()<\/td>\n<\/tr>\n<tr>\n<td>write_buffer_size<\/td>\n<td>\u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c<\/td>\n<td>4MB<\/td>\n<\/tr>\n<tr>\n<td>max_open_files<\/td>\n<td>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/td>\n<td>1000<\/td>\n<\/tr>\n<tr>\n<td>block_cache<\/td>\n<td>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0435\u0448 \u0434\u043b\u044f \u0431\u043b\u043e\u043a\u043e\u0432<\/td>\n<td>NULL, \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043a\u0435\u0448 \u043e\u0431\u044a\u0435\u043c\u043e\u043c 8MB <\/td>\n<\/tr>\n<tr>\n<td>block_size<\/td>\n<td>\u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0431\u043b\u043e\u043a\u0435<\/td>\n<td>4K<\/td>\n<\/tr>\n<tr>\n<td>compression<\/td>\n<td>\u0441\u0436\u0430\u0442\u0438\u0435 \u0431\u043b\u043e\u043a\u0430<\/td>\n<td>kSnappyCompression<\/td>\n<\/tr>\n<tr>\n<td>filter_policy<\/td>\n<td>\u0444\u0438\u043b\u044c\u0442\u0440(\u0411\u043b\u0443\u043c\u0430) \u0434\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0447\u0442\u0435\u043d\u0438\u044f \u0441 \u0434\u0438\u0441\u043a\u0430. <\/td>\n<td>NULL<\/td>\n<\/tr>\n<\/table>\n<h5><b>Slice<\/b><\/h5>\n<p>  Slice \u044d\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f \u043a\u043b\u044e\u0447 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0440\u044f\u0434\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432. Slice \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c Slice \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0431\u0443\u0444\u0435\u0440\u0430 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439:   <\/p>\n<pre><code class=\"cpp\">leveldb::Slice slice; if (...) {   std::string str = ...;   slice = str; } Use(slice); <\/code><\/pre>\n<p>  leveldb::Slice \u0438\u043c\u0435\u0435\u0442 \u0440\u044f\u0434 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:  <\/p>\n<pre><code class=\"cpp\">Slice(const char* d, size_t n) : data_(d), size_(n) { } Slice(const std::string& s) : data_(s.data()), size_(s.size()) { } Slice(const char* s) : data_(s), size_(strlen(s)) { } <\/code><\/pre>\n<p>  \u0418 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445  <\/p>\n<pre><code class=\"cpp\">const char* leveldb::Slice::data() const; char leveldb::Slice::operator[](size_t n) const; std::string leveldb::Slice::ToString() const; <\/code><\/pre>\n<h5><b>\u0421\u0442\u0430\u0442\u0443\u0441<\/b><\/h5>\n<p>  \u0414\u043b\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 LevelDB \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0441\u0442\u0430\u0442\u0443\u0441.<br \/>  \u041f\u043e \u0441\u0442\u0430\u0442\u0443\u0441\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0430\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438.  <\/p>\n<pre><code class=\"cpp\">leveldb::Status s = ...; if (!s.ok()) cerr &lt;&lt; s.ToString() &lt;&lt; endl; <\/code><\/pre>\n<h5><b>\u0427\u0442\u0435\u043d\u0438\u0435, \u0437\u0430\u043f\u0438\u0441\u044c, \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435<\/b><\/h5>\n<p>  \u0421\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b Put, Get, Delete:  <\/p>\n<pre><code class=\"cpp\">Status leveldb::DB::Put(const WriteOptions& options, const Slice& key, const Slice& value); Status leveldb::DB::Get(const ReadOptions& options, const Slice& key, std::string* value); Status leveldb::DB::Delete(const WriteOptions& options, const Slice& key); <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:  <\/p>\n<pre><code class=\"cpp\">std::string value; leveldb::Status s = db-&gt;Get(leveldb::ReadOptions(), key1, &value); if (s.ok()) s = db-&gt;Put(leveldb::WriteOptions(), key2, value); if (s.ok()) s = db-&gt;Delete(leveldb::WriteOptions(), key1); <\/code><\/pre>\n<h5><b>\u0418\u0442\u0435\u0440\u0430\u0442\u043e\u0440<\/b><\/h5>\n<p>  \u0418\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u043b\u0430\u0441\u0441\u043e\u043c leveldb::Iterator \u0438 \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:  <\/p>\n<pre><code class=\"cpp\">bool leveldb::Iterator::Valid() const; void leveldb::Iterator::SeekToFirst(); void leveldb::Iterator::SeekToLast(); void leveldb::Iterator::Seek(const Slice& target); void leveldb::Iterator::Next(); void leveldb::Iterator::Prev(); Slice leveldb::Iterator::key() const; Slice leveldb::Iterator::value() const; Status leveldb::Iterator::status() const; <\/code><\/pre>\n<p>  \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e <br \/>  \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043c\u043e\u0436\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u0441\u044f \u043a\u0430\u043a \u0432 \u043f\u0440\u044f\u043c\u043e\u043c, \u0442\u0430\u043a \u0438 \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u043c<br \/>  \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438.<\/p>\n<pre><code class=\"cpp\">leveldb::Iterator* it = db-&gt;NewIterator(leveldb::ReadOptions()); for (it-&gt;SeekToFirst(); it-&gt;Valid(); it-&gt;Next()) {   cout &lt;&lt; it-&gt;key().ToString() &lt;&lt; &quot;: &quot;  &lt;&lt; it-&gt;value().ToString() &lt;&lt; endl; } assert(it-&gt;status().ok());  \/\/ Check for any errors found during the scan delete it; <\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"cpp\">for (it-&gt;Seek(start);      it-&gt;Valid() && it-&gt;key().ToString() &lt; limit;      it-&gt;Next()) {   ... }  <\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"cpp\">for (it-&gt;SeekToLast(); it-&gt;Valid(); it-&gt;Prev()) {   ... } <\/code><\/pre>\n<h4><b><a name=\"2\"><\/a> \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 LevelDB, \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u044f\u0434\u043e\u0432.<\/b><\/h4>\n<p>  \u041c\u043e\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0440\u044f\u0434\u044b \u0438 <a href=\"http:\/\/en.wikipedia.org\/wiki\/Time_series_database\">time series database<\/a>. <\/p>\n<p>  \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c\u0441\u044f \u0434\u0432\u0443\u043c\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438:  <\/p>\n<ul>\n<li>\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li>\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430.<\/li>\n<\/ul>\n<h5><b>\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/b><\/h5>\n<p>  \u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0442\u0438\u043f\u0430 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0445\u0435\u043c\u0443: \u043a\u043b\u044e\u0447=\u043c\u0435\u0442\u0440\u0438\u043a\u0430+\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043c\u0435\u0442\u043a\u0430+\u0442\u0435\u0433\u0438(\u0442\u0435\u0433\u0438 \u043e\u043f\u0446\u0438\u0430\u043d\u0430\u043b\u044c\u043d\u044b).<br \/>  \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u0430 <a href=\"http:\/\/opentsdb.net\/\">OpenTSDB<\/a>, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0430\u044f \u043f\u043e\u0432\u0435\u0440\u0445 HBase.<br \/>  \u0412\u043d\u0443\u0442\u0440\u0438 OpenTSDB \u0435\u0441\u0442\u044c \u0441\u0445\u0435\u043c\u0430 uid&#8217;\u043e\u0432 \u043c\u0435\u0442\u0440\u0438\u043a \u0438 \u0441\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u0422\u0430\u043a\u043e\u0439 \u0436\u0435 \u043f\u0440\u0438\u043d\u0446\u044b\u043f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d \u0438 \u0437\u0434\u0435\u0441\u044c.<\/p>\n<p>  \u041e\u0434\u043d\u0430 \u0431\u0430\u0437\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043c\u0435\u0442\u0440\u0438\u043a. \u041a\u043b\u044e\u0447\u0435\u043c \u0442\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u0432 <b>size_t<\/b>, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0430 \u0432 \u0441\u0442\u0438\u043b\u0435 \u0421\u0438.<\/p>\n<p>  \u0412\u0442\u0440\u043e\u0430\u044f \u0431\u0430\u0437\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043e\u043f\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043b\u044e\u0447\u0435\u043c \u0442\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0432\u0438\u0434\u0430:  <\/p>\n<pre><code class=\"cpp\">struct Key {     size_t muid;     time_t timestamp; }; <\/code><\/pre>\n<p>  \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 <b>double<\/b>. \u0422\u0443\u0442 \u043d\u0430 \u043f\u043e\u043b\u043d\u0443\u044e \u043a\u0430\u0442\u0443\u0448\u043a\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u0442 \u0444\u0430\u043a\u0442, \u0447\u0442\u043e \u043a\u043b\u044e\u0447 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 LevelDB \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0430\u0439\u0442,<br \/>  \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u043e\u0439 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<h5><b>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430<\/b><\/h5>\n<pre><code class=\"cpp\">#pragma once  #include &lt;ctime&gt; #include &lt;cstdint&gt;  #include &lt;memory&gt; #include &lt;unordered_map&gt;  namespace leveldb {     class DB;     class Iterator;     class Slice;     class Comparator;     class Cache; }  \/*!  * \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043c\u0435\u0442\u0440\u0438\u043a  *\/ class Storage { public:     class Iterator;     typedef size_t MetricUid;      \/*!      * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430      *\/     struct Key     {         MetricUid muid;   \/\/!&lt; uid \u043c\u0435\u0442\u0440\u0438\u043a\u0438         time_t timestamp; \/\/!&lt; \u0432\u0440\u0435\u043c\u044f     };      \/*!      * \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440      * @param dir \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0431\u0430\u0437\u044b \u043c\u0435\u0442\u0440\u0438\u043a      * @param cacheSizeMb \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u043b\u043e\u043a\u0430 \u043a\u0435\u0448\u0430      *\/     Storage(const std::string& dir, size_t cacheSizeMb = 16);      \/*!      * @brief \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438.      * @param name \u0438\u043c\u044f \u043c\u0435\u0442\u0440\u0438\u043a\u0438      * @return \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043c\u0435\u0442\u0440\u0438\u043a\u0438      *      * \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u0440\u0438\u043a\u0443 \u0432 \u0431\u0430\u0437\u0443 UID'\u043e\u0432 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 UID \u043c\u0435\u0442\u0440\u0438\u043a\u0438.      * \u0415\u0441\u043b\u0438 \u043c\u0435\u0442\u0440\u0438\u043a\u0430 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430, \u0442\u043e \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 UID \u043c\u0435\u0442\u0440\u0438\u043a\u0438      *\/     MetricUid addMetric(const std::string& name);      \/*!      * \u0417\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435      * @param muid \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043c\u0435\u0442\u0440\u0438\u043a\u0438      * @param timestamp \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430      * @param value \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435      * @return true \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u043e\u0448\u0438\u0431\u043e\u043a      *\/     bool put(MetricUid muid, time_t timestamp, double value);      \/*!      * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043c\u0435\u0442\u0440\u0438\u043a\u0438      * @param muid \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043c\u0435\u0442\u0440\u0438\u043a\u0438      * @param from \u043d\u0430\u0447\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430      * @param to \u043a\u043e\u043d\u0435\u0446 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430      * @return \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440      *\/     Iterator get(MetricUid muid, time_t from, time_t to);      Storage(const Storage&) = delete;     Storage& operator=(const Storage&) = delete;  private:      \/*!      * \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b uid \u043c\u0435\u0442\u0440\u0438\u043a      *\/     void initUID();      \/*!      * \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445      *\/     void initData();  private:      \/*!      * \u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u0434\u043b\u044f UID      *\/     MetricUid m_currentIndx;      \/*!      * \u0411\u0430\u0437\u0430\u0432\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433      *\/     std::string m_dir;      \/*!      * \u0420\u0430\u0437\u043c\u0435\u0440 \u0431\u043b\u043e\u043a\u0430 \u043a\u0435\u0448\u0430      *\/     size_t m_cacheSizeMb;      \/*!      * \u041a\u0435\u0448 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445      *\/     std::shared_ptr&lt;leveldb::Cache&gt; m_dataCache;      \/*!      * \u0411\u0430\u0437\u0430 UID'\u043e\u0432      *\/     std::shared_ptr&lt;leveldb::DB&gt; m_uid;      \/*!      * \u0411\u0430\u0437\u0430 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439      *\/     std::shared_ptr&lt;leveldb::DB&gt; m_data;      \/*!      * \u041c\u044d\u043f \u043c\u0435\u0442\u0440\u0438\u043a\u0430 -&gt; uid      *\/     std::unordered_map&lt;std::string, MetricUid&gt; m_metric2uid; };  \/*!  * \u0418\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u0445\u043e\u0434\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445  *\/ class Storage::Iterator { public:     typedef std::tuple&lt;time_t, double&gt; Value;     typedef std::shared_ptr&lt;leveldb::Iterator&gt; IteratorPrivate;      Iterator();      Iterator(const IteratorPrivate& iter, const Key& limit);      \/*!      * \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0441\u0442\u044c      * @return true \u0435\u0441\u043b\u0438 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u0432\u0430\u043b\u0438\u0434\u0435\u043d      *\/     bool valid() const;      \/*!      * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435      * @return \u043a\u043e\u0440\u0442\u0435\u0436 &lt;\u0432\u0440\u0435\u043c\u044f, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435&gt;      *\/     Value value() const;      \/*!      * \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443      *\/     void next();  private:      IteratorPrivate m_iter; \/\/!&lt; \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440 LevelDB     Key m_limit; \/\/!&lt; \u043a\u043b\u044e\u0447 \u0434\u043b\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u043f\u0440\u0430\u0432\u0430 }; <\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 Storage \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0443\u0442\u044c \u043a \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0443, \u0433\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0442\u0441\u044f \u0431\u0430\u0437\u0430 \u0441 uid \u0438 \u0431\u0430\u0437\u0430 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u043b\u043e\u043a\u0430 \u043a\u0435\u0448\u0430.<\/p>\n<h5><b>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/b><\/h5>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043a\u043e\u043c\u043f\u0430\u0440\u0430\u0442\u043e\u0440\u0430, \u0442.\u043a. memcmp \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0447\u0438\u0441\u0435\u043b. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u044e\u0447\u0430, \u043a\u043e\u0434 \u043f\u0440\u043e\u0441\u0442 \u0438 \u0447\u0438\u0442\u0430\u0435\u043c:  <\/p>\n<pre><code class=\"cpp\">namespace {     class TimeMeasurementComporator: public leveldb::Comparator     {     public:         int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const         {             const char* dataA = a.data();             const char* dataB = b.data();             const Storage::Key* keyA =                     reinterpret_cast&lt;const Storage::Key*&gt;(dataA);             const Storage::Key* keyB =                     reinterpret_cast&lt;const Storage::Key*&gt;(dataB);             if (keyA-&gt;muid &lt; keyB-&gt;muid)             {                 return -1;             }             else if (keyA-&gt;muid &gt; keyB-&gt;muid)             {                 return 1;             }              if (keyA-&gt;timestamp &lt; keyB-&gt;timestamp)             {                 return -1;             }             else if (keyA-&gt;timestamp &gt; keyB-&gt;timestamp)             {                 return 1;             }              return 0;         }          \/\/ Ignore the following methods for now:         const char* Name() const         {             return &quot;TimeMeasurementComporator&quot;;         }         void FindShortestSeparator(std::string*, const leveldb::Slice&) const         {         }         void FindShortSuccessor(std::string*) const         {         }     };     TimeMeasurementComporator GLOBAL_COMPORATOR; } <\/code><\/pre>\n<p>  \u0414\u0430\u043b\u044c\u0448\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\/\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u044b \u043f\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"cpp\">void Storage::initData() {     DB* data;     Options options;     options.create_if_missing = true;     options.compression = kNoCompression;     options.comparator = &GLOBAL_COMPORATOR;      if (m_cacheSizeMb)     {         options.block_cache = leveldb::NewLRUCache(m_cacheSizeMb * 1048576);         m_dataCache.reset(options.block_cache);     }      Status status = DB::Open(options, m_dir + &quot;\/data&quot;, &data);     if (!status.ok())     {         LOG(ERROR)&lt;&lt;&quot;Error opening database &quot;&lt;&lt;status.ToString();         exit(1);     }     m_data.reset(data); } <\/code><\/pre>\n<p>  \u0412 \u043e\u043f\u0446\u0438\u044f\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u0430\u0440\u0430\u0442\u043e\u0440, \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0441\u0436\u0430\u0442\u0438\u0435 \u0442.\u043a. LelelDB \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0437 Snappy.<\/p>\n<p>  \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u043c\u0435\u0442\u0440\u0438\u043a:  <\/p>\n<pre><code class=\"cpp\">void Storage::initUID() {     Options options;     options.create_if_missing = true;     options.compression = kNoCompression;      DB* cfg;     Status status = DB::Open(options, m_dir + &quot;\/conf&quot;, &cfg);     if (!status.ok())     {         LOG(ERROR)&lt;&lt;&quot;Error opening database &quot;&lt;&lt;status.ToString();         exit(1);     }     m_uid.reset(cfg);      std::unique_ptr&lt;leveldb::Iterator&gt; it(             m_uid-&gt;NewIterator(leveldb::ReadOptions()));      for (it-&gt;SeekToFirst(); it-&gt;Valid(); it-&gt;Next())     {         const size_t* index = reinterpret_cast&lt;const size_t*&gt;(it-&gt;key().data());         m_metric2uid[it-&gt;value().ToString()] = *index;         m_currentIndx = *index;     } } <\/code><\/pre>\n<p>  \u0422\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0432 UID.<\/p>\n<p>  \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0435:  <\/p>\n<pre><code class=\"cpp\">Storage::MetricUid Storage::addMetric(const std::string& name) {     auto result = m_metric2uid.find(name);     if (result != m_metric2uid.end())     {         return result-&gt;second;     }     ++m_currentIndx;     m_metric2uid[name] = m_currentIndx;     const auto s = m_uid-&gt;Put(WriteOptions(),             Slice(reinterpret_cast&lt;const char*&gt;(&m_currentIndx), sizeof(m_currentIndx)),             name);      if (!s.ok())     {         LOG(ERROR)&lt;&lt;&quot;Error put &quot;&lt;&lt;s.ToString();     }      return m_currentIndx; }  bool Storage::put(MetricUid muid, time_t timestamp, double value) {     const Key key = {muid, timestamp};      const auto s = m_data-&gt;Put(WriteOptions(),             Slice(reinterpret_cast&lt;const char*&gt;(&key), sizeof(key)),             Slice(reinterpret_cast&lt;char*&gt;(&value), sizeof(value)));      if (!s.ok())     {         LOG(ERROR)&lt;&lt;&quot;Error put &quot;&lt;&lt;s.ToString();     }      return s.ok(); } <\/code><\/pre>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043d\u0430\u0434 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c LevelDB:  <\/p>\n<pre><code>Storage::Iterator Storage::get(MetricUid muid, time_t from, time_t to) {     const Key begin = {muid, from};     const Key end = { muid, to };      Storage::Iterator::IteratorPrivate iter(m_data-&gt;NewIterator(ReadOptions()));     iter-&gt;Seek(Slice(reinterpret_cast&lt;const char*&gt;(&begin),                      sizeof(begin)));     return Storage::Iterator(iter, end); }  Storage::Iterator::Iterator():         m_iter(nullptr) {     memset(&m_limit, 0, sizeof(m_limit)); }   Storage::Iterator::Iterator(const IteratorPrivate& iter, const Key& limit) :         m_iter(iter),         m_limit(limit) { }  bool Storage::Iterator::valid() const {     if(!m_iter)     {         return false;     }      const Slice right(reinterpret_cast&lt;const char*&gt;(&m_limit),                       sizeof(m_limit));      return m_iter-&gt;Valid() &&            (GLOBAL_COMPORATOR.Compare(m_iter-&gt;key(),right) &lt; 0); }  Storage::Iterator::Value Storage::Iterator::value() const {     if(!m_iter)     {         return Value(0,0);     }      const Key* data =reinterpret_cast&lt;const Key*&gt;(m_iter-&gt;key().data());     double val = *reinterpret_cast&lt;const double*&gt;(m_iter-&gt;value().data());     return Value(data-&gt;timestamp, val); }  void Storage::Iterator::next() {     if(m_iter && m_iter-&gt;Valid())     {         m_iter-&gt;Next();     } } <\/code><\/pre>\n<p>  \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u0434\u044b \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 <a href=\"https:\/\/github.com\/RPG-18\/tmdb\">GitHub<\/a>.<\/p>\n<p>  \u0418\u0437 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e:<br \/>  <a href=\"https:\/\/vimeo.com\/95313698\">\u041e\u0431\u0437\u043e\u0440 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435: LevelDB, TokuDB, LMDB, Sophia<\/a><br \/>  <a href=\"http:\/\/www.highload.ru\/2013\/abstracts\/1617.html\">\u0413\u043b\u0443\u0431\u043e\u043a\u043e\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0432 \u0434\u0438\u0441\u043a\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445, B-\u0434\u0435\u0440\u0435\u0432\u044c\u044f, LSM-\u0434\u0435\u0440\u0435\u0432\u044c\u044f \u0438 \u0444\u0440\u0430\u043a\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0435\u0440\u0435\u0432\u044c\u044f<\/a>     \t<\/p>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/256207\/\"> http:\/\/habrahabr.ru\/post\/256207\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>     \t\u0421\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0435\u0439, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0438 \u043a\u043e\u043b\u043b\u0435\u0433\u0438 \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u0433\u043e key-value \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 SQLite, MemcacheDB, Redis \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044f \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a LevelDB, Sophia, HamsterDB \u0438 \u0442.\u0434.<\/p>\n<p>  \u042f \u0440\u0430\u0437\u0431\u0438\u043b \u0441\u0442\u0430\u0442\u044c\u044e \u043d\u0430 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438:  <\/p>\n<ol>\n<li><a href=\"#1\">\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 api LevelDB;<\/a><\/li>\n<li><a href=\"#2\">\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 LevelDB, \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u044f\u0434\u043e\u0432.<\/a><\/li>\n<\/ol>\n<p>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-261378","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/261378","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=261378"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/261378\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=261378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=261378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=261378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}