bool Level::refreshBackgroundMusic(vector playerPos) { if(bgmusicActivated) { if(actualBackgroundMusic != NULL && vectorInCube(playerPos, actualBackgroundMusic->location)) return false; if(backgroundMusics->IsEmpty()) return false; ListIterator<locationMusic> i = ListIterator<locationMusic>(backgroundMusics); i.SetFirst(); do { if(vectorInCube(playerPos, i.GetCurrent()->location)) { actualBackgroundMusic = i.GetCurrent(); bgmusic->selectMusic(actualBackgroundMusic->musicname, -1); bgmusic->toggle(); return true; } i.Next(); }while(!i.IsLast()); if(actualBackgroundMusic != NULL) bgmusic->toggle(); actualBackgroundMusic = NULL; } return false; }
/** * @date 2011/12/21 * * Handler of a request. The WebService request si built from the request, and * forwarded to the correct WsInterface. * ******************************************************************************/ int32_t WsHandler::RequestReceived(const HttpdRequest &Request, HttpdRequest *Answer) { int32_t i_Ret = -1; ListIterator<AList<WsInterface*>, WsInterface*> Iterator; WsInterface *p_Interface = NULL; const String *RequestInterface; if(HandleCors(Request, Answer) == 0) return(0); DynObject Params; const uint8_t *Payload; uint32_t i_Length; i_Ret = Request.GetPayload(&Payload, &i_Length); if(i_Ret == 0) { JsonFlattener Flattener; const String PayloadString((const char*)(Payload), i_Length); i_Ret = Flattener.UnFlatten(&PayloadString, &Params); if(i_Ret == 0) { i_Ret = Params.FindString("InterfaceName", &RequestInterface); } } if(i_Ret != 0) return(-1); Iterator.SetTo(&InterfaceList); Iterator.First(); while(Iterator.IsDone() == false) { if( (Iterator.GetItem(&p_Interface) == 0) && (p_Interface != NULL) ) { if(p_Interface->GetName() == *RequestInterface) { String AnswerString; i_Ret = p_Interface->Call(Params, &AnswerString); if(i_Ret == 0) { i_Ret = Answer->SetPayload((const uint8_t*)AnswerString.GetString(), AnswerString.GetSize()); } break; } } Iterator.Next(); } return(i_Ret); }
int Ardb::RenameList(Context& ctx, DBID srcdb, const std::string& srckey, DBID dstdb, const std::string& dstkey) { Context tmpctx; tmpctx.currentDB = srcdb; ValueObject v; int err = GetMetaValue(tmpctx, srckey, LIST_META, v); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); if (0 != err) { fill_error_reply(ctx.reply, "no such key or some error"); return 0; } if (v.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { DelKeyValue(tmpctx, v.key); v.key.encode_buf.Clear(); v.key.db = dstdb; v.key.key = dstkey; v.meta.expireat = 0; SetKeyValue(ctx, v); } else { ListIterator iter; ListIter(ctx, v, iter, false); tmpctx.currentDB = dstdb; ValueObject dstmeta; dstmeta.key.type = KEY_META; dstmeta.key.key = dstkey; dstmeta.type = LIST_META; dstmeta.meta.SetFlag(COLLECTION_FLAG_SEQLIST); dstmeta.meta.SetEncoding(COLLECTION_ENCODING_ZIPLIST); BatchWriteGuard guard(GetKeyValueEngine()); while (iter.Valid()) { std::string tmpstr; ListInsert(tmpctx, dstmeta, NULL, iter.Element()->GetDecodeString(tmpstr), false, false); iter.Next(); } SetKeyValue(tmpctx, dstmeta); tmpctx.currentDB = srcdb; DeleteKey(tmpctx, srckey); } ctx.data_change = true; return 0; }
void main() { Recipe myRecipe1 = Recipe("Fish Filets in Hot Chili Oil"); Recipe myRecipe2 = Recipe("Boiled Fish with Pickled Cabbage and Chili "); Recipe myRecipe3 = Recipe("Coke Chicken"); Recipe myRecipe4 = Recipe("Fish ball soup"); List<Recipe>* myRecipeList = new List<Recipe>(); myRecipeList->Append(myRecipe1); myRecipeList->Append(myRecipe2); myRecipeList->Append(myRecipe3); myRecipeList->Append(myRecipe4); ListIterator<Recipe> myIterator = ListIterator<Recipe>(myRecipeList); for(myIterator.First(); !myIterator.IsDone(); myIterator.Next()) { myIterator.CurrentItem().Print(); } while(1) { ; } }
ObjectType *ObjectTypeCache::searchObjectType(const char *objtypename) { ObjectType *result = NULL; ListIterator<ObjectType> i = ListIterator<ObjectType>(cachedObjectTypes); i.SetFirst(); while(!(i.IsLast())) { result = i.GetCurrent(); if(!strncmp(result->objectTypeName, objtypename, MAX_STRING_LENGTH)) break; else result = NULL; i.Next(); } return result; }
int Ardb::LClear(Context& ctx, ValueObject& meta) { BatchWriteGuard guard(GetKeyValueEngine(), meta.meta.Encoding() != COLLECTION_ENCODING_ZIPLIST); if (meta.meta.Encoding() != COLLECTION_ENCODING_ZIPLIST) { ListIterator iter; meta.meta.len = 0; ListIter(ctx, meta, iter, false); while (iter.Valid()) { KeyObject fk; fk.db = ctx.currentDB; fk.key = meta.key.key; fk.type = LIST_ELEMENT; fk.score = *(iter.Score()); DelKeyValue(ctx, fk); iter.Next(); } } DelKeyValue((ctx), meta.key); return 0; }
bool ObjectTypeCache::unloadObjectType(const char *objtypename) { ObjectType *objTypeToDelete = NULL; ListIterator<ObjectType> i = ListIterator<ObjectType>(cachedObjectTypes); i.SetFirst(); while(!(i.IsLast())) { objTypeToDelete = i.GetCurrent(); if(!strncmp(objTypeToDelete->objectTypeName, objtypename, MAX_STRING_LENGTH)) { i.Remove(); return true; } i.Next(); } return false; }
TEST(HttpdRequestTestGroup, Basic) { String SetPath(PATH1 ); HttpdRequest Obj1; /* Path */ const String &GetPath1 = Obj1.GetPath(); CHECK(GetPath1 == ""); CHECK(Obj1.SetPath(SetPath) == 0); const String &GetPath2 = Obj1.GetPath(); CHECK(GetPath2 == SetPath); /* Status */ CHECK(Obj1.GetStatus() == 200); Obj1.SetStatus(404); CHECK(Obj1.GetStatus() == 404); /* Method */ CHECK(Obj1.GetMethod() == HttpdRequest::NONE); Obj1.SetMethod(HttpdRequest::POST); CHECK(Obj1.GetMethod() == HttpdRequest::POST); /* payload */ uint8_t SetPayload[326]; const uint8_t *GetPayload; uint32_t i_Length; CHECK(Obj1.SetPayload(SetPayload, 326) == 0); CHECK(Obj1.GetPayload(&GetPayload, &i_Length) == 0); CHECK(i_Length == 326); CHECK(memcmp(GetPayload, SetPayload, i_Length) == 0); /* Header */ String Header1Name(HEADER1), Header2Name(HEADER2); String Header1Val(HEADER1VAL), Header2Val(HEADER2VAL); String HeaderVal; CHECK(Obj1.GetHeader(Header1Name, &HeaderVal) == -1); CHECK(Obj1.SetHeader(Header1Name, Header1Val) == 0); CHECK(Obj1.GetHeader(Header1Name, &HeaderVal) == 0); CHECK(HeaderVal == Header1Val); CHECK(Obj1.SetHeader(Header2Name, Header2Val) == 0); CHECK(Obj1.GetHeader(Header2Name, &HeaderVal) == 0); CHECK(HeaderVal == Header2Val); CHECK(Obj1.SetHeader(Header1Name, Header2Val) == 0); CHECK(Obj1.GetHeader(Header1Name, &HeaderVal) == 0); CHECK(HeaderVal == Header2Val); /* Header list */ const AList<HttpdRequest::Header*> &HeaderList = Obj1.GetHeaderList(); ListIterator<AList<HttpdRequest::Header*>, HttpdRequest::Header*> Iterator; HttpdRequest::Header *p_CurHeader; uint32_t i_Index = 0; Iterator.SetTo(&HeaderList); Iterator.First(); while(Iterator.IsDone() == false) { CHECK(Iterator.GetItem(&p_CurHeader) == 0); CHECK(p_CurHeader != NULL); CHECK(i_Index <= 1); switch(i_Index) { case 0: CHECK(p_CurHeader->Name == Header1Name); CHECK(p_CurHeader->Value == Header2Val); break; case 1: CHECK(p_CurHeader->Name == Header2Name); CHECK(p_CurHeader->Value == Header2Val); break; } i_Index++; Iterator.Next(); } };
int Ardb::LTrim(Context& ctx, RedisCommandFrame& cmd) { int64 start, end; if (!GetInt64Value(ctx, cmd.GetArguments()[1], start) || !GetInt64Value(ctx, cmd.GetArguments()[2], end)) { return 0; } ValueObject meta; int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); if (0 != err) { fill_status_reply(ctx.reply, "OK"); return 0; } /* convert negative indexes */ if (start < 0) start = meta.meta.Length() + start; if (end < 0) end = meta.meta.Length() + end; if (start < 0) start = 0; if (end >= meta.meta.Length()) end = meta.meta.Length() - 1; /* Invariant: start >= 0, so this test will be true when end < 0. * The range is empty when start > end or start >= length. */ if (start > end || start >= meta.meta.Length()) { /* Out of range start or start > end result in empty list */ DeleteKey(ctx, cmd.GetArguments()[0]); return 0; } if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { DataArray newzip; for (int64 i = start; i <= end; i++) { newzip.push_back(meta.meta.ziplist[i]); } meta.meta.ziplist = newzip; SetKeyValue(ctx, meta); } else { BatchWriteGuard guard(GetKeyValueEngine()); if (meta.meta.IsSequentialList()) { int64 listlen = meta.meta.Length(); for (int64 s = 0; s < listlen; s++) { if (s == start) { s = end; continue; } KeyObject lk; lk.db = meta.key.db; lk.key = meta.key.key; lk.type = LIST_ELEMENT; lk.score = meta.meta.min_index.IncrBy(s); meta.meta.len--; DelKeyValue(ctx, lk); } meta.meta.max_index = meta.meta.min_index; meta.meta.min_index.IncrBy(start); meta.meta.max_index.IncrBy(end); } else { ListIterator iter; ListIter(ctx, meta, iter, false); int64 cursor = 0; while (iter.Valid()) { if (cursor < start || cursor > end) { DelRaw(ctx, iter.CurrentRawKey()); meta.meta.len--; } if (cursor == start) { meta.meta.min_index = *(iter.Element()); } else if (cursor == end) { meta.meta.max_index = *(iter.Element()); } cursor++; iter.Next(); } } SetKeyValue(ctx, meta); } return 0; }
int Ardb::LSet(Context& ctx, RedisCommandFrame& cmd) { int64 index; if (!GetInt64Value(ctx, cmd.GetArguments()[1], index)) { fill_error_reply(ctx.reply, "value is not an integer or out of range"); return 0; } ValueObject meta; int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); if (0 != err) { fill_error_reply(ctx.reply, "no such key"); return 0; } if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { Data* entry = GetZipEntry(meta.meta.ziplist, index); if (NULL == entry) { fill_error_reply(ctx.reply, "index out of range"); return 0; } else { entry->SetString(cmd.GetArguments()[2], true); SetKeyValue(ctx, meta); fill_status_reply(ctx.reply, "OK"); return 0; } } else { if (index >= meta.meta.Length() || (-index) > meta.meta.Length()) { fill_error_reply(ctx.reply, "index out of range"); return 0; } if (meta.meta.IsSequentialList()) { ValueObject list_element; list_element.key.db = meta.key.db; list_element.key.key = meta.key.key; list_element.key.type = LIST_ELEMENT; list_element.key.score = meta.meta.min_index; if (index >= 0) { list_element.key.score.IncrBy(index); } else { list_element.key.score.IncrBy(index + meta.meta.Length()); } if (0 == GetKeyValue(ctx, list_element.key, &list_element)) { list_element.element.SetString(cmd.GetArguments()[2], true); SetKeyValue(ctx, list_element); fill_status_reply(ctx.reply, "OK"); return 0; } } else { ListIterator iter; ListIter(ctx, meta, iter, index < 0); int64 cursor = index >= 0 ? 0 : -1; while (iter.Valid()) { if (cursor == index) { ValueObject v; v.key.db = meta.key.db; v.key.key = meta.key.key; v.key.type = LIST_ELEMENT; v.key.score = *(iter.Score()); v.type = LIST_ELEMENT; v.element.SetString(cmd.GetArguments()[2], true); SetKeyValue(ctx, v); fill_status_reply(ctx.reply, "OK"); return 0; } if (cursor >= 0) { cursor++; } else { cursor--; } if (index < 0) { iter.Prev(); } else { iter.Next(); } } } fill_error_reply(ctx.reply, "index out of range"); } return 0; }
int Ardb::LRem(Context& ctx, RedisCommandFrame& cmd) { int64 count; if (!GetInt64Value(ctx, cmd.GetArguments()[1], count)) { return 0; } int64 toremove = std::abs(count); ValueObject meta; int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); if (0 != err) { fill_int_reply(ctx.reply, 0); return 0; } Data element; element.SetString(cmd.GetArguments()[2], true); KeyLockerGuard lock(m_key_lock, ctx.currentDB, cmd.GetArguments()[0]); if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { uint32 oldlen = meta.meta.ziplist.size(); int64 removed = 0; DataArray newzip; if (count >= 0) { for (uint32 i = 0; i < oldlen; i++) { if (meta.meta.ziplist[i] == element) { if (toremove == 0 || removed < toremove) { removed++; continue; } } newzip.push_back(meta.meta.ziplist[i]); } } else { for (uint32 i = 0; i < oldlen; i++) { if (meta.meta.ziplist[oldlen - 1 - i] == element) { if (toremove == 0 || removed < toremove) { removed++; continue; } } newzip.push_front(meta.meta.ziplist[i]); } } if (removed > 0) { meta.meta.ziplist = newzip; SetKeyValue(ctx, meta); } fill_int_reply(ctx.reply, removed); return 0; } BatchWriteGuard guard(GetKeyValueEngine()); ListIterator iter; ListIter(ctx, meta, iter, count < 0); int64 remove = 0; while (iter.Valid()) { if (iter.Element()->Compare(element) == 0) { meta.meta.len--; meta.meta.SetFlag(COLLECTION_FLAG_NORMAL); DelRaw(ctx, iter.CurrentRawKey()); //DelKeyValue(ctx, k); remove++; if (remove == toremove) { break; } } if (count < 0) { iter.Prev(); } else { iter.Next(); } } if (remove > 0) { SetKeyValue(ctx, meta); } fill_int_reply(ctx.reply, remove); return 0; }
int Ardb::LIndex(Context& ctx, RedisCommandFrame& cmd) { int64 index; if (!GetInt64Value(ctx, cmd.GetArguments()[1], index)) { return 0; } ValueObject meta; int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); if (0 != err) { ctx.reply.type = REDIS_REPLY_NIL; return 0; } if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { Data* entry = GetZipEntry(meta.meta.ziplist, index); if (NULL != entry) { fill_value_reply(ctx.reply, *entry); } else { ctx.reply.type = REDIS_REPLY_NIL; } return 0; } else { if ((index >= 0 && index >= meta.meta.Length()) || (index < 0 && (meta.meta.Length() + index) < 0)) { ctx.reply.type = REDIS_REPLY_NIL; return 0; } ListIterator iter; if (meta.meta.IsSequentialList()) { err = SequencialListIter(ctx, meta, iter, index); if (0 == err) { if (iter.Valid()) { fill_value_reply(ctx.reply, *(iter.Element())); return 0; } } } else { err = ListIter(ctx, meta, iter, index < 0); uint32 cursor = index < 0 ? 1 : 0; while (iter.Valid()) { if (cursor == std::abs(index)) { fill_value_reply(ctx.reply, *(iter.Element())); return 0; } cursor++; if (index >= 0) { iter.Next(); } else { iter.Prev(); } } } ctx.reply.type = REDIS_REPLY_NIL; } return 0; }
int Ardb::ListRange(Context& ctx, const Slice& key, int64 start, int64 end) { ValueObject meta; int err = GetMetaValue(ctx, key, LIST_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); /* convert negative indexes */ if (start < 0) start = meta.meta.Length() + start; if (end < 0) end = meta.meta.Length() + end; if (start < 0) start = 0; /* Invariant: start >= 0, so this test will be true when end < 0. * The range is empty when start > end or start >= length. */ ctx.reply.type = REDIS_REPLY_ARRAY; if (start > end || start >= meta.meta.Length()) { return 0; } if (end >= meta.meta.Length()) end = meta.meta.Length() - 1; int64 rangelen = (end - start) + 1; if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { uint32 i = start; while (rangelen-- && i < meta.meta.ziplist.size()) { RedisReply& r = ctx.reply.AddMember(); fill_value_reply(r, meta.meta.ziplist[i++]); } } else { ListIterator iter; if (meta.meta.IsSequentialList()) { SequencialListIter(ctx, meta, iter, start); uint32 count = 0; while (iter.Valid() && count < rangelen) { RedisReply& r = ctx.reply.AddMember(); fill_value_reply(r, iter.Element()); count++; iter.Next(); } } else { if (start > meta.meta.len / 2) { start -= meta.meta.len; end -= meta.meta.len; } ListIter(ctx, meta, iter, start < 0); int64 cursor = start < 0 ? -1 : 0; while (iter.Valid()) { if (cursor >= start && cursor <= end) { RedisReply& r = ctx.reply.AddMember(); fill_value_reply(r, iter.Element()); } if (start < 0) { if (cursor < start) { break; } cursor--; } else { if (cursor > end) { break; } cursor++; } iter.Next(); } } } return 0; }
int Ardb::ListInsert(Context& ctx, ValueObject& meta, const std::string* match, const std::string& value, bool head, bool abort_nonexist) { if (WakeBlockList(ctx, meta.key.key, value)) { fill_int_reply(ctx.reply, 1); return 0; } if (NULL != match) { if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { Data element; element.SetString(value, true); DataArray::iterator zit = meta.meta.ziplist.begin(); while (zit != meta.meta.ziplist.end()) { std::string tmp; zit->GetDecodeString(tmp); if (tmp == *match) { break; } zit++; } if (zit == meta.meta.ziplist.end()) { fill_int_reply(ctx.reply, 0); return 0; } if (head) { meta.meta.ziplist.insert(zit, element); } else { zit++; if (zit != meta.meta.ziplist.end()) { meta.meta.ziplist.insert(zit, element); } else { meta.meta.ziplist.push_back(element); } } if (meta.meta.Length() > 1 && (meta.meta.Length() >= m_cfg.list_max_ziplist_entries || element.StringLength() >= m_cfg.list_max_ziplist_value)) { //convert to non ziplist ZipListConvert(ctx, meta); } } else { ListIterator iter; ListIter(ctx, meta, iter, false); std::string tmp; Data prev, next; Data current; bool matched = false; while (iter.Valid()) { if (iter.Element()->GetDecodeString(tmp) == (*match)) { current = *(iter.Score()); matched = true; if (head) { break; } } if (head) { prev = *(iter.Score()); iter.Next(); } else { if (matched) { next = *(iter.Score()); break; } } iter.Next(); } if (!matched) { fill_int_reply(ctx.reply, 0); return 0; } Data score; if (head) { if (prev.IsNil()) { score = current.IncrBy(-1); } else { score.SetDouble((prev.NumberValue() + current.NumberValue()) / 2); meta.meta.SetFlag(COLLECTION_FLAG_NORMAL); } } else { if (next.IsNil()) { score = current.IncrBy(1); } else { score.SetDouble((next.NumberValue() + current.NumberValue()) / 2); meta.meta.SetFlag(COLLECTION_FLAG_NORMAL); } } meta.meta.len++; ValueObject v; v.type = LIST_ELEMENT; v.element.SetString(value, true); v.key.db = meta.key.db; v.key.key = meta.key.key; v.key.type = LIST_ELEMENT; v.key.score = score; SetKeyValue(ctx, v); } fill_int_reply(ctx.reply, meta.meta.Length()); return 0; } else { if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { Data element; element.SetString(value, true); if (head) { meta.meta.ziplist.push_front(element); } else { meta.meta.ziplist.push_back(element); } if (meta.meta.Length() >= m_cfg.list_max_ziplist_entries || element.StringLength() >= m_cfg.list_max_ziplist_value) { //convert to non ziplist ZipListConvert(ctx, meta); } } else { meta.meta.len++; ValueObject v; v.type = LIST_ELEMENT; v.element.SetString(value, true); v.key.db = meta.key.db; v.key.key = meta.key.key; v.key.type = LIST_ELEMENT; if (head) { v.key.score = meta.meta.min_index.IncrBy(-1); } else { v.key.score = meta.meta.max_index.IncrBy(1); } SetKeyValue(ctx, v); } fill_int_reply(ctx.reply, meta.meta.Length()); return 0; } }
int Ardb::ListPop(Context& ctx, const std::string& key, bool lpop) { ValueObject meta; KeyLockerGuard keylock(m_key_lock, ctx.currentDB, key); int err = GetMetaValue(ctx, key, LIST_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); if (0 != err) { ctx.reply.type = REDIS_REPLY_NIL; return 0; } BatchWriteGuard guard(GetKeyValueEngine(), meta.meta.Encoding() != COLLECTION_ENCODING_ZIPLIST); if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST) { if (!meta.meta.ziplist.empty()) { if (lpop) { Data& data = meta.meta.ziplist.front(); fill_value_reply(ctx.reply, data); meta.meta.ziplist.pop_front(); } else { Data& data = meta.meta.ziplist.back(); fill_value_reply(ctx.reply, data); meta.meta.ziplist.pop_back(); } if (meta.meta.ziplist.empty()) { DelKeyValue(ctx, meta.key); } else { SetKeyValue(ctx, meta); } } else { ctx.reply.type = REDIS_REPLY_NIL; } return 0; } else { bool poped = false; if (meta.meta.IsSequentialList()) { if (meta.meta.Length() > 0) { ValueObject lkv; lkv.key.type = LIST_ELEMENT; lkv.key.key = meta.key.key; lkv.key.db = ctx.currentDB; lkv.key.score = lpop ? meta.meta.min_index : meta.meta.max_index; if (0 == GetKeyValue(ctx, lkv.key, &lkv)) { DelKeyValue(ctx, lkv.key); if (lpop) { meta.meta.min_index.IncrBy(1); } else { meta.meta.max_index.IncrBy(-1); } meta.meta.len--; poped = true; fill_value_reply(ctx.reply, lkv.element); } } } else { ListIterator iter; err = ListIter(ctx, meta, iter, !lpop); while (iter.Valid()) { if (!poped) { fill_value_reply(ctx.reply, *(iter.Element())); poped = true; meta.meta.len--; KeyObject k; k.type = LIST_ELEMENT; k.key = meta.key.key; k.db = ctx.currentDB; k.score = *(iter.Score()); DelKeyValue(ctx, k); } else { if (lpop) { meta.meta.min_index = *(iter.Score()); } else { meta.meta.max_index = *(iter.Score()); } break; } if (lpop) { iter.Next(); } else { iter.Prev(); } } } if (poped) { if (meta.meta.Length() > 0) { SetKeyValue(ctx, meta); } else { DelKeyValue(ctx, meta.key); } } else { ctx.reply.type = REDIS_REPLY_NIL; } return 0; } }