bool Ardb::DBExist(const DBID& db, DBID& nextdb) { KeyObject start(Slice(), KV, db); Iterator* iter = FindValue(start, false); bool found = false; nextdb = db; if (NULL != iter && iter->Valid()) { Slice tmpkey = iter->Key(); KeyObject* kk = decode_key(tmpkey, NULL); if (NULL != kk) { if (kk->db == db) { found = true; } else { nextdb = kk->db; } } DELETE(kk); } DELETE(iter); return found; }
int Ardb::FlushScripts() { KeyObject start(Slice(), SCRIPT, ARDB_GLOBAL_DB); Iterator* iter = FindValue(start, false); BatchWriteGuard guard(GetEngine()); while (NULL != iter && iter->Valid()) { Slice tmpkey = iter->Key(); KeyObject* kk = decode_key(tmpkey, NULL); if (NULL != kk) { if (kk->type == SCRIPT) { DelValue(*kk); } else { break; } } DELETE(kk); iter->Next(); } DELETE(iter); return 0; }
void Ardb::PrintDB(const DBID& db) { Slice empty; KeyObject start(empty, KV, db); Iterator* iter = FindValue(start); while (NULL != iter && iter->Valid()) { Slice tmpkey = iter->Key(); KeyObject* kk = decode_key(tmpkey, NULL); if (kk->db != db) { DELETE(kk); break; } ValueObject v; Buffer readbuf(const_cast<char*>(iter->Value().data()), 0, iter->Value().size()); decode_value(readbuf, v, false); if (NULL != kk) { std::string str; DEBUG_LOG("[%d]Key=%s, Value=%s", kk->type, kk->key.data(), v.ToString(str).c_str()); } DELETE(kk); iter->Next(); } DELETE(iter); }
void Ardb::Walk(WalkHandler* handler) { KeyObject start(Slice(), KV, 0); Iterator* iter = FindValue(start); uint32 cursor = 0; while (NULL != iter && iter->Valid()) { Slice tmpkey = iter->Key(); KeyObject* kk = decode_key(tmpkey, NULL); if (NULL == kk) { break; } ValueObject v; Buffer readbuf(const_cast<char*>(iter->Value().data()), 0, iter->Value().size()); decode_value(readbuf, v, false); int ret = handler->OnKeyValue(kk, &v, cursor++); DELETE(kk); if (ret < 0) { break; } iter->Next(); } DELETE(iter); }
void Ardb::Walk(KeyObject& key, bool reverse, WalkHandler* handler) { bool isFirstElement = true; Iterator* iter = FindValue(key); if (NULL != iter && !iter->Valid() && reverse) { iter->SeekToLast(); isFirstElement = false; } uint32 cursor = 0; while (NULL != iter && iter->Valid()) { Slice tmpkey = iter->Key(); KeyObject* kk = decode_key(tmpkey, &key); if (NULL == kk || kk->type != key.type || kk->key.compare(key.key) != 0) { DELETE(kk); if (reverse && isFirstElement) { iter->Prev(); isFirstElement = false; continue; } break; } ValueObject v; Buffer readbuf(const_cast<char*>(iter->Value().data()), 0, iter->Value().size()); decode_value(readbuf, v, false); int ret = handler->OnKeyValue(kk, &v, cursor++); DELETE(kk); if (ret < 0) { break; } if (reverse) { iter->Prev(); } else { iter->Next(); } } DELETE(iter); }
int Ardb::FirstDB(DBID& db) { int ret = -1; Iterator* iter = NewIterator(); iter->SeekToFirst(); if (NULL != iter && iter->Valid()) { Slice tmpkey = iter->Key(); KeyObject* kk = decode_key(tmpkey, NULL); if (NULL != kk) { db = kk->db; ret = 0; } DELETE(kk); } DELETE(iter); return ret; }
int Ardb::LastDB(DBID& db) { int ret = -1; Iterator* iter = NewIterator(ARDB_GLOBAL_DB); if (NULL != iter && iter->Valid()) { //Skip last KEY_END entry iter->Prev(); } if (NULL != iter && iter->Valid()) { Slice tmpkey = iter->Key(); KeyObject* kk = decode_key(tmpkey, NULL); if (NULL != kk) { db = kk->db; ret = 0; } DELETE(kk); } DELETE(iter); return ret; }
int Ardb::Scan(Context& ctx, RedisCommandFrame& cmd) { StringArray keys; std::string pattern; uint32 limit = 10000; //return max 10000 keys one time if (cmd.GetArguments().size() > 1) { for (uint32 i = 1; i < cmd.GetArguments().size(); i++) { if (!strcasecmp(cmd.GetArguments()[i].c_str(), "count")) { if (i + 1 >= cmd.GetArguments().size() || !string_touint32(cmd.GetArguments()[i + 1], limit)) { fill_error_reply(ctx.reply, "value is not an integer or out of range"); return 0; } i++; } else if (!strcasecmp(cmd.GetArguments()[i].c_str(), "match")) { if (i + 1 >= cmd.GetArguments().size()) { fill_error_reply(ctx.reply, "'MATCH' need one args followed"); return 0; } pattern = cmd.GetArguments()[i + 1]; i++; } else { fill_error_reply(ctx.reply, "Syntax error, try scan 0 "); return 0; } } } RedisReply& r1 = ctx.reply.AddMember(); RedisReply& r2 = ctx.reply.AddMember(); r2.type = REDIS_REPLY_ARRAY; KeyObject from; from.db = ctx.currentDB; from.type = KEY_META; const std::string& cursor = cmd.GetArguments()[0]; std::string scan_start_cursor; if (cmd.GetArguments()[0] != "0") { if (m_cfg.scan_redis_compatible) { FindElementByRedisCursor(cursor, scan_start_cursor); } from.key = scan_start_cursor; } Iterator* iter = IteratorKeyValue(from, false); bool reachend = false; std::string tmpkey; while (NULL != iter && iter->Valid()) { KeyObject kk; if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META) { reachend = true; break; } tmpkey.clear(); tmpkey.assign(kk.key.data(), kk.key.size()); if (r2.MemberSize() >= limit) { break; } if ((pattern.empty() || stringmatchlen(pattern.c_str(), pattern.size(), tmpkey.c_str(), tmpkey.size(), 0) == 1)) { RedisReply& rr1 = r2.AddMember(); fill_str_reply(rr1, tmpkey); } iter->Next(); } if (reachend || !iter->Valid()) { fill_str_reply(r1, "0"); } else { if (m_cfg.scan_redis_compatible) { uint64 newcursor = GetNewRedisCursor(tmpkey); fill_str_reply(r1, stringfromll(newcursor)); } else { fill_str_reply(r1, tmpkey); } } DELETE(iter); return 0; }
int Ardb::KeysOperation(Context& ctx, const KeysOptions& options) { KeyObject from; from.db = ctx.currentDB; from.type = KEY_META; std::string::size_type cursor = options.pattern.find("*"); if (cursor == std::string::npos) { from.key = options.pattern; } else { if (options.pattern != "*" && cursor > 0) { from.key = options.pattern.substr(0, cursor); } } Iterator* iter = IteratorKeyValue(from, false); std::string tmpkey; uint32 count = 0; while (NULL != iter && iter->Valid()) { KeyObject kk; if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META) { break; } tmpkey.clear(); tmpkey.assign(kk.key.data(), kk.key.size()); if ((options.pattern == "*" || stringmatchlen(options.pattern.c_str(), options.pattern.size(), tmpkey.data(), tmpkey.size(), 0) == 1)) { if (options.op == OP_GET) { RedisReply& r = ctx.reply.AddMember(); fill_str_reply(r, tmpkey); } else { count++; } } else { /* * If the '*' is the last char, we can break iteration now */ if (cursor == options.pattern.size() - 1) { break; } } iter->Next(); } DELETE(iter); if (options.op == OP_GET) { ctx.reply.type = REDIS_REPLY_ARRAY; } else { fill_int_reply(ctx.reply, count); } return 0; }
int Ardb::Randomkey(Context& ctx, RedisCommandFrame& cmd) { ctx.reply.type = REDIS_REPLY_NIL; KeyObject from; from.db = ctx.currentDB; from.type = KEY_META; std::string min_key, max_key, randkey; Iterator* iter = IteratorKeyValue(from, false); if (iter->Valid()) { KeyObject kk; if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META) { goto _end; } min_key.assign(kk.key.data(), kk.key.size()); max_key = min_key; from.type = SET_ELEMENT; //Refer comparator.cpp from.encode_buf.Clear(); IteratorSeek(iter, from); if (!iter->Valid()) { iter->SeekToLast(); } if (iter->Valid()) { iter->Prev(); if (iter->Valid()) { if (decode_key(iter->Key(), kk) && kk.db == ctx.currentDB && kk.type == KEY_META) { max_key.assign(kk.key.data(), kk.key.size()); } } } randkey = min_key; if (min_key < max_key) { randkey = random_between_string(min_key, max_key); from.type = KEY_META; from.db = ctx.currentDB; from.key = randkey; IteratorSeek(iter, from); if (iter->Valid()) { KeyObject kk; if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META) { goto _end; } randkey.assign(kk.key.data(), kk.key.size()); } } } if (!randkey.empty()) { fill_str_reply(ctx.reply, randkey); } _end: DELETE(iter); return 0; }