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(); } } }
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); } }
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 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); }
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; }
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; }
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); } }
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; }
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(); }
/** 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); } } } }
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; }
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; }