void CoroutineService::on_update(const int64_t now){ Super::on_update(now); // wakeup sleeper if(m_sleeper_table->size() > 0){ // prepare wake up list Int64Array* wake_list =0; HashIterator* it =static_cast< HashIterator* >(m_sleeper_table->iterator()); while(it->next()){ Int64* cr_id =static_cast< Int64* >(it->getKey()); Int64* expire_time =static_cast< Int64* >(it->getValue()); if(expire_time->getValue() > now){ if(!wake_list){ wake_list =SafeNew<Int64Array>(); } wake_list->push_back(cr_id->getValue()); it->remove(); } } // wake up const int64_t n =wake_list ? wake_list->size() : 0; for(int64_t i=0; i<n; ++i){ _resume_coroutine(wake_list->get(i), SafeNew<Error>(ErrorCode::TIMEOUT), 0); } } // update int64_t cr_new_id=0; m_cr_pool->go(_update, 0, cr_new_id); }
int Ardb::HashLen(Context& ctx, const Slice& key) { ValueObject meta; int err = GetMetaValue(ctx, key, HASH_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); if (err == ERR_NOT_EXIST) { fill_int_reply(ctx.reply, 0); } else { if (meta.meta.Length() < 0) { HashIterator iter; meta.meta.len = 0; HashIter(ctx, meta, "", iter, true); while (iter.Valid()) { meta.meta.len++; iter.Next(); } SetKeyValue(ctx, meta); } fill_int_reply(ctx.reply, meta.meta.Length()); } return 0; }
void CoroutinePool::finalize(){ m_cleaning =true; // clean idle list for(int64_t i=0; i<m_idle_coroutine_list->size(); ++i){ Coroutine* cr =static_cast< Coroutine* >(m_idle_coroutine_list->get(i)); cr->resume(SafeNew<Error>(ErrorCode::COROUTINE_CLEAN), 0); ASSERT(cr->getStatus() == Coroutine::STATUS_DEAD); } CLEAN_POINTER(m_idle_coroutine_list); // clean active table Hash* active_cr_tb =m_active_coroutine_table; m_active_coroutine_table =0; HashIterator* it =static_cast< HashIterator* >(active_cr_tb->iterator()); while(it->next()){ Coroutine* cr =static_cast< Coroutine* >(it->getValue()); cr->resume(SafeNew<Error>(ErrorCode::COROUTINE_CLEAN), 0); ASSERT(cr->getStatus() == Coroutine::STATUS_DEAD); } CLEAN_POINTER(active_cr_tb); // super Super::finalize(); }
void Hash::forEach(void (*pfn)(Object*, Object*, void*), void* userdata){ if(!pfn) return; HashIterator* it =dynamic_cast<HashIterator*>(iterator()); while(it->next()){ pfn(it->getKey(), it->getValue(), userdata); } }
int Ardb::HashGetAll(Context& ctx, const Slice& key, RedisReply& reply) { ValueObject meta; int err = GetMetaValue(ctx, key, HASH_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); reply.type = REDIS_REPLY_ARRAY; if (0 != err) { return 0; } HashIterator iter; err = HashIter(ctx, meta, "", iter, true); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); reply.type = REDIS_REPLY_ARRAY; while (iter.Valid()) { const Data* field = iter.Field(); Data* value = iter.Value(); RedisReply& r = reply.AddMember(); fill_value_reply(r, *field); RedisReply& r1 = reply.AddMember(); fill_value_reply(r1, *value); iter.Next(); } return 0; }
Array* Actor::getAllComponent(){ Array* ret =SafeNew<Array>(); HashIterator* it =static_cast< HashIterator* >(m_component_manager->iterator()); while(it->next()){ ret->push_back(it->getValue()); } return ret; }
status_t Directory::Rewind(void *cookie) { HashIterator *iterator = (HashIterator *)cookie; iterator->Rewind(); return B_OK; }
Object * Hash::clone(){ Hash* new_obj =core::SafeNew<Hash>(); HashIterator* it =dynamic_cast<HashIterator*>(this->iterator()); while(it->next()){ new_obj->set(it->getKey(), it->getValue()); } return new_obj; }
void Hash::removeIf(bool (*pfn)(Object*, Object*)){ if(!pfn) return; HashIterator* it =dynamic_cast<HashIterator*>(iterator()); while(it->next()){ if(pfn(it->getKey(), it->getValue())){ it->remove(); } } }
void CommandService::_optimize(const int64_t now) { if(m_queue_tb->size() > OPTIMIZE_THRESHOLD) { HashIterator* it =static_cast< HashIterator* >(m_queue_tb->iterator()); while(it->next()) { Array* queue =static_cast< Array* >(it->getValue()); if(queue->empty()) { it->remove(); } } m_queue_tb->optimize(0); } }
status_t Directory::GetNextEntry(void *cookie, char *name, size_t size) { HashIterator *iterator = (HashIterator *)cookie; int32 block; NodeBlock *node = iterator->GetNext(block); if (node == NULL) return B_ENTRY_NOT_FOUND; return node->GetName(name, size); }
int Ardb::HClear(Context& ctx, ValueObject& meta) { BatchWriteGuard guard(GetKeyValueEngine(), meta.meta.encoding != COLLECTION_ECODING_ZIPMAP); if (meta.meta.encoding != COLLECTION_ECODING_ZIPMAP) { HashIterator iter; HashIter(ctx, meta, "", iter, false); while (iter.Valid()) { DelRaw(ctx, iter.CurrentRawKey()); iter.Next(); } } DelKeyValue(ctx, meta.key); return 0; }
void CommandService::_process_timeout(const int64_t now) { /* clear timeout command */ if(m_queue_tb->size()>0) { Int64Array* ls =0; HashIterator* it =static_cast< HashIterator* >(m_queue_tb->iterator()); while(it->next()) { const int64_t who =static_cast< Int64* >(it->getKey())->getValue(); Array* queue =static_cast< Array* >(it->getValue()); while(Command* cmd =dynamic_cast< Command* >(queue->front())) { if(cmd->isTimeout(now)) { if(cmd->isProcessing()) { WARN("service %s(%lld) who %lld command %lld cancel", name(), (long long)m_id, (long long)cmd->getWho(), (long long)cmd->getCommand()); } queue->pop_front(); } else { break; } } if(Command* cmd =dynamic_cast< Command* >(queue->front())) { if(cmd->isProcessing()) { continue; } ASSERT(cmd->isInit()); if(!ls) { ls =SafeNew<Int64Array>(); } ls->push_back(who); } } const int64_t n= ls ? ls->size() : 0; for(int64_t i=0; i<n; ++i) { _process_request(ls->get(i)); } } /* clear timeout rpc */ if(m_rpc_tb->size()>0) { Array* ls =0; HashIterator* it =static_cast< HashIterator* >(m_rpc_tb->iterator()); while(it->next()) { RpcInfo* ri =static_cast< RpcInfo* >(it->getValue()); if(now >= ri->getExpireTime()) { if(!ls) { ls =SafeNew<Array>(); } ls->push_back(ri); it->remove(); } } const int64_t n =ls ? ls->size() : 0; for(int64_t i=0; i<n; ++i) { RpcInfo* ri =static_cast< RpcInfo* >(ls->get(i)); WARN("service %s(%lld) rpc %lld cancel", name(), (long long)m_id, (long long)ri->getId()); ri->timeout(); } } }
status_t Directory::Open(void **_cookie, int mode) { _inherited::Open(_cookie, mode); HashIterator *iterator = new(nothrow) HashIterator(fVolume.Device(), fNode); if (iterator == NULL) return B_NO_MEMORY; if (iterator->InitCheck() != B_OK) { delete iterator; return B_NO_MEMORY; } *_cookie = (void *)iterator; return B_OK; }
Int64Array* ServiceManager::_get_need_unload_service_id(){ std::lock_guard<LOCK_TYPE> guard(m_lock); if(m_unloading_service_tb->empty()){ return 0; } const int64_t now =DateTime::Now(); Int64Array* arr =SafeNew<Int64Array>(); HashIterator* it =static_cast< HashIterator* >(m_unloading_service_tb->iterator()); while(it->next()){ const int64_t id_srv =static_cast< Int64* >(it->getKey())->getValue(); const int64_t t =static_cast< Int64* >(it->getValue())->getValue(); if(now >= t){ arr->push_back(id_srv); it->remove(); } } return arr; }
int Ardb::RenameHash(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, HASH_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_ECODING_ZIPMAP) { 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 { HashIterator iter; HashIter(ctx, v, "", iter, false); tmpctx.currentDB = dstdb; ValueObject dstmeta; dstmeta.key.type = KEY_META; dstmeta.key.key = dstkey; dstmeta.type = HASH_META; dstmeta.meta.encoding = COLLECTION_ECODING_ZIPMAP; BatchWriteGuard guard(GetKeyValueEngine()); while (iter.Valid()) { HashSet(tmpctx, dstmeta, *(iter.Field()), *(iter.Value())); iter.Next(); } SetKeyValue(tmpctx, dstmeta); tmpctx.currentDB = srcdb; DeleteKey(tmpctx, srckey); } ctx.data_change = true; return 0; }
void ServiceManager::unloadAllService(){ OPH(); // prepare service table Hash* srv_tb =0; { std::lock_guard<LOCK_TYPE> guard(m_lock); srv_tb =static_cast< Hash* >(m_service_tb->clone()); m_service_tb->clear(); m_route_tb->clear(); m_unloading_service_tb->clear(); } // unload HashIterator* it =static_cast< HashIterator* >(srv_tb->iterator()); while(it->next()){ Service* service =static_cast< Service* >(it->getValue()); if(service){ service->unload(); } } srv_tb->clear(); }
int Ardb::HVals(Context& ctx, RedisCommandFrame& cmd) { ValueObject meta; int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); ctx.reply.type = REDIS_REPLY_ARRAY; if (0 != err) { return 0; } HashIterator iter; err = HashIter(ctx, meta, "", iter, true); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); ctx.reply.type = REDIS_REPLY_ARRAY; while (iter.Valid()) { Data* value = iter.Value(); RedisReply& r = ctx.reply.AddMember(); fill_value_reply(r, *value); iter.Next(); } return 0; }
int Ardb::HKeys(Context& ctx, RedisCommandFrame& cmd) { ValueObject meta; int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); ctx.reply.type = REDIS_REPLY_ARRAY; if (0 != err) { return 0; } HashIterator iter; err = HashIter(ctx, meta, "", iter, true); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); ctx.reply.type = REDIS_REPLY_ARRAY; while (iter.Valid()) { const Data* value = iter.Field(); RedisReply& r = ctx.reply.AddMember(); std::string tmp; fill_str_reply(r, value->GetDecodeString(tmp)); iter.Next(); } return 0; }
/** coroutine manager **/ void CoroutinePool::update(const int64_t now){ // process timeout if(m_active_coroutine_table && m_active_coroutine_table->size()>0){ // prepare Int64Array* ls =0; HashIterator* it =static_cast< HashIterator* >(m_active_coroutine_table->iterator()); while(it->next()){ Coroutine* cr =static_cast< Coroutine* >(it->getValue()); if(cr->isWaitingAndExpire(now)){ if(!ls){ ls =SafeNew<Int64Array>(); } ls->push_back(cr->getId()); } } // resume if(ls && ls->size()>0){ const int64_t n =ls->size(); for(int64_t i=0; i<n; ++i){ resume(ls->get(i), SafeNew<Error>(ErrorCode::TIMEOUT), 0); } } } }
Iterator* Hash::iterator(){ HashIterator* it =SafeNew<HashIterator>(); it->bind(this); return it; }
Object* HashIterator::clone(){ HashIterator* it =SafeNew<HashIterator>(); it->bind(m_hash); return it; }
bool Url::_build(String* protocol, String* auth, String* host, String* path, String* query_string, Hash* query, String* fragment){ // clean clean(); // check if(path && path->size() && !path->hasPrefix("/")){ return false; } // make url BinaryCoder<1024> coder; if(protocol && protocol->size()){ ASSIGN_POINTER(m_protocol, protocol); coder.append(protocol); coder.append("://", 3); } if(auth && auth->size()){ ASSIGN_POINTER(m_auth, auth); coder.append(auth); coder.append("@", 1); } if(host && host->size()){ ASSIGN_POINTER(m_host, host); coder.append(host); } if(path && path->size()){ ASSIGN_POINTER(m_path, path); coder.append(path); } if(query_string && query_string->size()){ ASSIGN_POINTER(m_query_string, query_string); ASSIGN_POINTER(m_query, SafeNew<Hash>()); if(!ParseQuery(m_query_string, m_query)){ clean(); return false; } coder.append("?", 1); coder.append(m_query_string); } else if(query && query->size()){ ASSIGN_POINTER(m_query, query); // make query string BinaryCoder<1024> sub_coder; HashIterator* it =static_cast< HashIterator* >(query->iterator()); while(it->next()){ String* key =static_cast< String* >(it->getKey()); String* val =static_cast< String* >(it->getValue()); if(sub_coder.size() > 0){ sub_coder.append("&", 1); } sub_coder.append(UrlEncode::Encode(key)); sub_coder.append("=", 1); sub_coder.append(UrlEncode::Encode(val)); } // set ASSERT(sub_coder.size()); ASSIGN_POINTER(m_query_string, String::New(sub_coder.c_str(), sub_coder.size())); coder.append("?", 1); coder.append(m_query_string); } if(fragment && fragment->size()){ ASSIGN_POINTER(m_fragment, fragment); coder.append("#", 1); coder.append(fragment); } ASSIGN_POINTER(m_url, String::New(coder.c_str(), coder.size())); return true; }
bool HttpRespond::flush(){ // check if(m_requestor == 0){ WARN("http flush failed, requestor is null"); return false; } //// build data BinaryCoder<4096> coder; /// head line // version if(m_version){ coder.append(m_version); } else{ coder.append("HTTP/1.1"); } coder.append(" "); // code coder.append(String::Format("%lld", (long long)m_code)); coder.append(" "); // msg coder.append(_code_to_msg(m_code)); coder.append("\r\n"); /// header if(!m_header_tb->has("Content-Type")){ coder.append("Content-Type: text/html\r\n"); } if(!m_header_tb->has("Content-Length")){ coder.append(String::Format("Content-Length: %lld\r\n", (long long)m_content->size())); } HashIterator* it =static_cast< HashIterator* >(m_header_tb->iterator()); while(it->next()){ if(String* name =dynamic_cast< String* >(it->getKey())){ if(String* value =dynamic_cast< String* >(it->getValue())){ coder.append(name); coder.append(": "); coder.append(value); coder.append("\r\n"); } } } it =static_cast< HashIterator* >(m_cookie_tb->iterator()); while(it->next()){ if(dynamic_cast< String* >(it->getKey())){ if(HttpCookie* cookie =dynamic_cast< HttpCookie* >(it->getValue())){ if(String* str =cookie->build(false)){ coder.append(str); coder.append("\r\n"); } } } } coder.append("\r\n"); /// content if(m_content->size() > 0){ coder.append(m_content->c_str(), m_content->size()); } //// send const bool ok =m_requestor->send(coder.c_str(), coder.size()); //// clear CLEAN_POINTER(m_version); m_code =200; CLEAN_POINTER(m_msg); m_header_tb->clear(); m_cookie_tb->clear(); m_content->clear(); //// post process if(!ok){ close(); } m_auto_flush =false; return ok; }
int Ardb::HScan(Context& ctx, RedisCommandFrame& cmd) { std::string pattern; uint32 limit = 10000; //return max 10000 keys one time if (cmd.GetArguments().size() > 2) { for (uint32 i = 2; 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; } } } ValueObject meta; int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta); CHECK_ARDB_RETURN_VALUE(ctx.reply, err); RedisReply& r1 = ctx.reply.AddMember(); RedisReply& r2 = ctx.reply.AddMember(); r2.type = REDIS_REPLY_ARRAY; if (0 != err) { fill_str_reply(r1, "0"); return 0; } const std::string& cursor = cmd.GetArguments()[1]; HashIterator iter; HashIter(ctx, meta, cursor == "0" ? "" : cursor, iter, true); while (iter.Valid()) { const Data* field = iter.Field(); std::string tmp; field->GetDecodeString(tmp); if ((pattern.empty() || fnmatch(pattern.c_str(), tmp.c_str(), 0) == 0)) { RedisReply& rr1 = r2.AddMember(); RedisReply& rr2 = r2.AddMember(); fill_str_reply(rr1, tmp); fill_value_reply(rr2, *(iter.Value())); } if (r2.MemberSize() >= (limit * 2)) { break; } iter.Next(); } if (iter.Valid()) { iter.Next(); const Data* next_field = iter.Field(); std::string tmp; fill_str_reply(r1, next_field->GetDecodeString(tmp)); } else { fill_str_reply(r1, "0"); } return 0; }