|
|
@@ -4,8 +4,11 @@ |
|
|
|
**/ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <algorithm> |
|
|
|
#include <thread> |
|
|
|
#include <unordered_map> |
|
|
|
#include <utility> |
|
|
|
#include <rocksdb/db.h> |
|
|
|
|
|
|
|
#include "args.hpp" |
|
|
@@ -20,6 +23,41 @@ static void cleanup() { |
|
|
|
delete db; |
|
|
|
} |
|
|
|
|
|
|
|
static void filter_match(vector<string> &selv, string &&key, const string &value) { |
|
|
|
vector<rocksdb::Status> sts; |
|
|
|
vector<string> values; |
|
|
|
|
|
|
|
// 1. retrieve values |
|
|
|
{ |
|
|
|
string sufx = "." + move(key); |
|
|
|
vector<string> keys; |
|
|
|
vector<rocksdb::Slice> key_slices; |
|
|
|
keys.reserve(selv.size()); |
|
|
|
key_slices.reserve(selv.size()); |
|
|
|
for(const auto &i : selv) |
|
|
|
key_slices.emplace_back(keys.emplace_back(i + sufx)); |
|
|
|
string().swap(sufx); |
|
|
|
sts = db->MultiGet({}, key_slices, &values); |
|
|
|
} |
|
|
|
|
|
|
|
// 2. find matches |
|
|
|
{ |
|
|
|
auto it_s = sts.begin(); |
|
|
|
auto it_v = values.begin(); |
|
|
|
auto it_sel = selv.begin(); |
|
|
|
|
|
|
|
while(it_sel != selv.end()) { |
|
|
|
if(!it_s->ok() || *it_v != value) { |
|
|
|
it_s = sts.erase(it_s); |
|
|
|
it_v = values.erase(it_v); |
|
|
|
it_sel = selv.erase(it_sel); |
|
|
|
continue; |
|
|
|
} |
|
|
|
++it_s; ++it_v; ++it_sel; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#define AC(C) case ztdb::args_t::C: |
|
|
|
|
|
|
|
int main(const int argc, char *argv[]) { |
|
|
@@ -51,7 +89,7 @@ int main(const int argc, char *argv[]) { |
|
|
|
if(!st.ok()) |
|
|
|
errmsg(2, "db open failed: " + st.ToString()); |
|
|
|
} |
|
|
|
|
|
|
|
atexit(cleanup); |
|
|
|
|
|
|
|
switch(args.cmd) { |
|
|
|
AC(GET) |
|
|
@@ -160,16 +198,31 @@ int main(const int argc, char *argv[]) { |
|
|
|
AC(MATCH) |
|
|
|
{ |
|
|
|
if(args.cmd_args.empty()) |
|
|
|
errmsg(1, "invalid invocation to 'zstreedb2 m KEY VALUE'"); |
|
|
|
errmsg(1, "invalid invocation to 'zstreedb2 m (KEY VALUE)+'"); |
|
|
|
|
|
|
|
vector<string> selv; |
|
|
|
|
|
|
|
{ |
|
|
|
const string key = "." + args.sel_node; |
|
|
|
const auto it = db->NewIterator({}); |
|
|
|
for(it->SeekToFirst(); it->Valid(); it->Next()) |
|
|
|
if(it->key().ends_with(key) && it->value() == args.cmd_args.front()) { |
|
|
|
auto slc = it->key(); |
|
|
|
slc.remove_suffix(key.size()); |
|
|
|
selv.emplace_back(slc.data(), slc.size()); |
|
|
|
} |
|
|
|
delete it; |
|
|
|
} |
|
|
|
|
|
|
|
const string key = "." + args.sel_node; |
|
|
|
const auto it = db->NewIterator({}); |
|
|
|
for(it->SeekToFirst(); it->Valid(); it->Next()) |
|
|
|
if(it->key().ends_with(key) && it->value() == args.cmd_args.front()) { |
|
|
|
auto slc = it->key(); |
|
|
|
slc.remove_suffix(key.size()); |
|
|
|
printf("%.*s\n", static_cast<int>(slc.size()), slc.data()); |
|
|
|
} |
|
|
|
args.cmd_args.erase(args.cmd_args.begin()); |
|
|
|
auto it = args.cmd_args.begin(); |
|
|
|
while(it != args.cmd_args.end() && (it + 1) != args.cmd_args.end()) { |
|
|
|
filter_match(selv, std::move(*it), *(it + 1)); |
|
|
|
it += 2; |
|
|
|
} |
|
|
|
|
|
|
|
for(const auto &i : selv) |
|
|
|
printf("%.*s\n", static_cast<int>(i.size()), i.data()); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|