void ApplicationBase::finalize(){ // misc { OPH(); // actor & observer ActorManager::Release(); ObserverManager::Release(); // process local ProcessLocal::Release(); // monitor & logger Monitor::Release(); Logger::Release(); // path setDataPath(0); } // basic ObjectPool::Release(); ::clean_platform(); Super::finalize(); }
/** Object **/ void ApplicationBase::init(){ Super::init(); // basic ::init_platform(); ObjectPool::Set(New<ObjectPool>()); // misc { OPH(); // logger & monitor Logger::Init(); Monitor::Init(); // process local ProcessLocal::Init(); // register register_misc(); register_lua(); register_protocol(); register_class(); // observer & actor ObserverManager::Init(); ActorManager::Init(); } }
/** private **/ void Logger::_open_file(){ // check if(!m_szName || m_szName->empty()) return; OPH(); const time_t now =stable_time(); if(m_file){ if(ferror(m_file) || ((int64_t)now - m_file_open_time) > m_file_life_time){ fclose(m_file); m_file =0; } } if(m_file) return; // prepare time tm tmp; const tm* t =localtime_r(&now, &tmp); if(!t){ printf("fail to call localtime_r, %s\n", get_last_error_desc()); return; } // open String* path =String::Format("../log/%s_%04d%02d%02d%02d", m_szName->c_str(), t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour); m_file =fopen(path->c_str(), "a"); if(m_file){ m_file_open_time =now; } else{ printf("fail to open %s, %s\n", path->c_str(), get_last_error_desc()); } }
void ServiceManager::unloadServiceAfter(const int64_t id, const int64_t secs){ OPH(); std::lock_guard<LOCK_TYPE> guard(m_lock); if(m_route_tb->has(id)){ m_unloading_service_tb->set(id, SafeNew< Int64 >(DateTime::Now() + MAX(secs, UNLOAD_SERVICE_MIN_TIMER))); } }
void ApplicationBase::register_class(){ OPH(); LogService::RegisterClass(); TcpListener::RegisterClass(); HttpListener::RegisterClass(); HttpService::RegisterClass(); }
/** Object **/ void ProcessLocal::init(){ OPH(); Super::init(); // basic layer m_object_factory =New<ObjectFactory>(); RETAIN_POINTER(m_object_factory); m_string_table =New<StringTable>(); RETAIN_POINTER(m_string_table); m_protocol_manager =New<ProtocolManager>(); RETAIN_POINTER(m_protocol_manager); m_lua_init_callback =New<Array>(); RETAIN_POINTER(m_lua_init_callback); // kernel layer m_dispatcher_manager =New<DispatcherManager>(); RETAIN_POINTER(m_dispatcher_manager); m_network =New<Network>(); RETAIN_POINTER(m_network); m_service_manager =New<ServiceManager>(); RETAIN_POINTER(m_service_manager); // add dispatcher m_dispatcher_manager->addDispatcher(m_service_manager); m_dispatcher_manager->addDispatcher(m_network); OutputDebug("process local init [ ok ]"); }
void test_memory(){ OPH(); DEBUG("testing memory ......"); static void* pl[10000] ={0}; for(int i=0; i< 10000; ++i){ pl[i] =ALLOCATE(43); } for(int i=0; i< 10000; ++i){ DEALLOCATE(pl[i]); } /* performance check const int64_t N =100000; auto clk_a =clock(); for(int64_t i=0; i<N; ++i){ FREE(MALLOC(rand() % 8096 + 1)); } auto clk_b =clock(); void* p; for(int64_t i=0; i<N; ++i){ p=(malloc(rand() % 8096+ 1)); } auto clk_c =clock(); printf("%p %f\n", p, (clk_c-clk_b) / (clk_b+0. - clk_a)); */ // test memcpy PACKET src; src.size =1; PACKET dst; dst.size =0; PerformanceTest<100000>("memcpy", [&](){ memcpy(&dst, &src, sizeof(src)); }); PerformanceTest<100000>("oph", [&](){ OPH(); }); Object* x =SafeNew< Int64 >(); PerformanceTest<100000>("SafeNew", [&](){ OPH(); x =SafeNew< Bytes >(); }); }
void ServiceManager::finalize(){ OPH(); unloadAllService(); CLEAN_POINTER(m_unloading_service_tb); CLEAN_POINTER(m_service_tb); CLEAN_POINTER(m_route_tb); OutputDebug("service manager released [ ok ]"); Super::finalize(); }
/** Service **/ bool CoroutineService::on_load(){ if(!Super::on_load()) return false; OPH(); ASSIGN_POINTER(m_name, STR("CoroutineService")); ASSIGN_POINTER(m_command_desc_table, SafeNew<Hash>()); ASSIGN_POINTER(m_sleeper_table, SafeNew<Hash>()); ASSIGN_POINTER(m_cr_pool, SafeNew<CoroutinePool>()); register_command(); return true; }
void ServiceManager::unloadService(const int64_t id){ OPH(); int64_t id_beg =0; int64_t id_end =0; if(!_get_and_del_service_range(id, id_beg, id_end)){ return; } for(int64_t i=id_beg; i<id_end; ++i){ if(Service* service =_retain_and_del_service_direct(i)){ service->unload(); service->release(); } } }
/** self **/ void ApplicationBase::run(const int argc, const char** argv){ OPH(); // on load if(!on_load(argc, argv)){ ERROR("Core load failed"); return; } // run ProcessLocal* process =ProcessLocal::Instance(); while(process->update()); // on unload on_unload(); }
void ProcessLocal::finalize(){ OPH(); // clear dispatcher m_dispatcher_manager->clearDispatcher(); CLEAN_POINTER(m_service_manager); CLEAN_POINTER(m_network); CLEAN_POINTER(m_dispatcher_manager); CLEAN_POINTER(m_lua_init_callback); CLEAN_POINTER(m_protocol_manager); CLEAN_POINTER(m_string_table); CLEAN_POINTER(m_object_factory); Super::finalize(); OutputDebug("process local released [ ok ]"); }
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(); }
void ApplicationBase::register_lua(){ OPH(); ProcessLocal* pl =ProcessLocal::Instance(); pl->registerLuaInitCallback(HttpClientForLua::RegisterToLua); pl->registerLuaInitCallback(Requestor::RegisterToLua); pl->registerLuaInitCallback(ProtocolBase::RegisterToLua); pl->registerLuaInitCallback(ProtocolManager::RegisterToLua); pl->registerLuaInitCallback(Md5::RegisterToLua); pl->registerLuaInitCallback(Sha::RegisterToLua); pl->registerLuaInitCallback(Base64::RegisterToLua); pl->registerLuaInitCallback(XmlForLua::RegisterToLua); pl->registerLuaInitCallback(JsonForLua::RegisterToLua); pl->registerLuaInitCallback(UrlEncode::RegisterToLua); pl->registerLuaInitCallback(CharsetConvert::RegisterToLua); pl->registerLuaInitCallback(MysqlForLua::RegisterToLua); pl->registerLuaInitCallback(DispatcherManager::RegisterToLua); pl->registerLuaInitCallback(LogService::RegisterToLua); pl->registerLuaInitCallback(core::cpplua::register_cpplua); // pl->registerLuaInitCallback(core::data::register_cpplua); // pl->registerLuaInitCallback(core::protocol::register_cpplua); }
void test_cycle_buffer(){ OPH(); DEBUG("testing cycle buffer ......"); char data[1024]; for(uint64_t i=0; i<sizeof(data); ++i){ data[i] =i; } CycleBuffer *cb =SafeNew<CycleBuffer>(); cb->setCapacity(10240); cb->push(data, sizeof(data)); char data1[1024] ={0}; cb->pop(data1, 1024); CHECK_EXIT(0==memcmp(data1, data, sizeof(data)), 1); memset(data1, 0, sizeof(data1)); cb->push(data, sizeof(data)); cb->pop(data1, 512); cb->pop(data1+512, 512); CHECK_EXIT(0==memcmp(data1, data, sizeof(data)), 1); }
/** load unload **/ bool ApplicationBase::on_load(const int argc, const char** argv){ OPH(); // prepare path if(argc > 1){ INFO("data path is %s", argv[1]); setDataPath(STR(argv[1])); } else{ INFO("data path is ../data/"); setDataPath(STR("../data/")); } // load core::Network* net =core::Network::Instance(); bool ok =net->load(_config_path("startup/network.lua")); CHECK_EXIT(ok && "load network failed", 1); ok =ServiceManager::Instance()->load(_config_path("startup/service_manager.lua")); CHECK_EXIT(ok && "load service manager failed", 1); ok =ActorManager::Instance()->load(_config_path("startup/actor_manager.lua")); CHECK_EXIT(ok && "load actor manager failed", 1); return ok; }
/** register lua **/ void ApplicationBase::register_misc(){ OPH(); Base64::Init(); }
/* Service */ bool CService::load_module(const int64_t id, const char* path){ if(!Super::load_module(id, path)) return false; if(!path) return false; m_id =id; // load dll m_dl =::dlopen(path, RTLD_NOW | RTLD_GLOBAL); if(m_dl == 0){ const char* err =::dlerror(); ERROR("fail to call dlopen <%s>, %s", path, err ? err : "no error"); return false; } // object pool manager OPH(); // set path String* p =String::NewString(path); ASSIGN_POINTER(m_path, p); // get name { const char* (*fn_get_name)() =(const char* (*)())::dlsym(m_dl, "get_name"); if(!fn_get_name){ const char* err =::dlerror(); ERROR("fail to call dlsym <%s, get_name>, %s", path, err ? err : "no error"); unload_module(); return false; } const char* name =fn_get_name(); if(!name) name ="unnamed"; CLEAN_POINTER(m_name); m_name =String::NewString(name); m_name->retain(); } // get desc { const char* (*fn_get_desc)() =(const char* (*)())::dlsym(m_dl, "get_desc"); if(!fn_get_desc){ const char* err =::dlerror(); ERROR("fail to call dlsym <%s, get_desc>, %s", path, err ? err : "no error"); unload_module(); return false; } const char* desc =fn_get_desc(); if(!desc) desc =""; CLEAN_POINTER(m_desc); m_desc =String::NewString(desc); m_desc->retain(); } // get on_load { m_on_load =(PFN_ON_LOAD)::dlsym(m_dl, "on_load"); if(!m_on_load){ const char* err =::dlerror(); ERROR("fail to call dlsym <%s, on_load>, %s", path, err ? err : "no error"); unload_module(); return false; } } // get on_update { m_on_update =(PFN_ON_UPDATE)::dlsym(m_dl, "on_update"); if(!m_on_update){ const char* err =::dlerror(); ERROR("fail to call dlsym <%s, on_update>, %s", path, err ? err : "no error"); unload_module(); return false; } } // get on_start_command { m_on_start_command =(PFN_ON_START_COMMAND)::dlsym(m_dl, "on_start_command"); if(!m_on_start_command){ const char* err =::dlerror(); ERROR("fail to call dlsym <%s, on_start_command>, %s", path, err ? err : "no error"); unload_module(); return false; } } // get on_unload { m_on_unload =(PFN_ON_UNLOAD)::dlsym(m_dl, "on_unload"); if(!m_on_unload){ const char* err =::dlerror(); ERROR("fail to call dlsym <%s, on_unload>, %s", path, err ? err : "no error"); unload_module(); return false; } } return true; }
void test_lua(){ OPH(); DEBUG("testing lua ......"); test_lua_internal(); }
void test_array(){ OPH(); DEBUG("testing array ......"); Array* a =SafeNew<Array>(); for(int64_t i=0; i<14; ++i){ a->push_back(SafeNew<Int32>()); } for(int64_t i=0; i<14; ++i){ a->pop_back(); } ASSERT(a->empty()); // common array { Array* arr =SafeNew<Array>(); // push_back, size, pop_front, front for(int i=0; i<100; ++i){ arr->push_back(String::Format("%d", i)); } for(int i=0; i<100; ++i){ CHECK_EXIT(((String*)(arr->front()))->is(String::Format("%d", i)), 1); arr->pop_front(); } CHECK_EXIT(arr->size()==0, 1); // push_front, size, pop_back, back for(int i=99; i>=0; --i){ arr->push_front(String::Format("%d", i)); } CHECK_EXIT(arr->size()==100, 1); for(int i=99; i>=0; --i){ CHECK_EXIT(((String*)(arr->back()))->is(String::Format("%d", i)), 1); arr->pop_back(); } CHECK_EXIT(arr->size()==0, 1); // insert, remove for(int i=0; i<100; ++i){ arr->push_back(SafeNew<Int64, int64_t>(i)); } arr->push_front(SafeNew<Int64, int64_t>(-1)); arr->push_back(SafeNew<Int64, int64_t>(100)); for(int i=0; i<102; ++i){ CHECK_EXIT(((Int64*)(arr->get(i)))->getValue() == i-1, 1); } arr->insert(50, SafeNew<Int64, int64_t>(9999)); CHECK_EXIT(((Int64*)(arr->get(50)))->getValue() == 9999, 1); CHECK_EXIT(((Int64*)(arr->get(51)))->getValue() == 49, 1); CHECK_EXIT(((Int64*)(arr->get(49)))->getValue() == 48, 1); arr->remove(102); arr->remove(50); arr->remove(0); for(int i=0; i<100; ++i){ CHECK_EXIT(((Int64*)(arr->front()))->getValue() == i, 1); arr->pop_front(); } CHECK_EXIT(arr->size()==0, 1); } // int64 array { Int64Array* arr =SafeNew<Int64Array>(); // push_back, size, pop_front, front for(int i=0; i<100; ++i){ arr->push_back(i); } for(int i=0; i<100; ++i){ CHECK_EXIT(arr->front() == i, 1); arr->pop_front(); } CHECK_EXIT(arr->size()==0, 1); // push_front, size, pop_back, back for(int i=99; i>=0; --i){ arr->push_front(i); } CHECK_EXIT(arr->size()==100, 1); for(int i=99; i>=0; --i){ CHECK_EXIT(arr->back() == i, 1); arr->pop_back(); } CHECK_EXIT(arr->size()==0, 1); // insert, remove for(int i=0; i<100; ++i){ arr->push_back(i); } arr->push_front(-1); arr->push_back(100); for(int i=0; i<102; ++i){ CHECK_EXIT(arr->get(i) == i-1, 1); } arr->insert(50, 9999); CHECK_EXIT(arr->get(50) == 9999, 1); CHECK_EXIT(arr->get(51) == 49, 1); CHECK_EXIT(arr->get(49) == 48, 1); arr->remove(102); arr->remove(50); arr->remove(0); for(int i=0; i<100; ++i){ CHECK_EXIT(arr->front() == i, 1); arr->pop_front(); } CHECK_EXIT(arr->size()==0, 1); } }
void ApplicationBase::register_protocol(){ OPH(); core::protocol::register_protocol(); }
/** update **/ bool ProcessLocal::update(){ OPH(); const int64_t now =DateTime::Now(); m_service_manager->update(now); return m_network->update(now); }
int64_t ServiceManager::loadService(const char* path, const int64_t id_srv, const int64_t id_beg, const int64_t id_end, const int64_t alg_type){ if(!path) return -1; if(!_can_load_service(id_srv)){ WARN("loading service %s failed, service id %lld, begin id %lld, end id %lld, algrithm %lld, reason is already exist or unloading", path, (long long)id_srv, (long long)id_beg, (long long)id_end, (long long)alg_type); return -1; } OPH(); INFO("loading service %s, service id %lld, begin id %lld, end id %lld, algrithm %lld", path, (long long)id_srv, (long long)id_beg, (long long)id_end, (long long)alg_type); if(0==id_srv && 0==id_end && 0==id_beg){ if(Service* service =_load_service(0, path)){ if(_add_service(service)){ service->release(); // set service id range const int64_t id =service->getId(); RangeId* service_id =SafeNew<RangeId>(); service_id->setRange(id, id+1); service_id->setAlgrithm(alg_type); _set_service_id(id, service_id); return id; } else{ service->unload(); service->release(); return -1; } } else{ return -1; } } else if(id_srv>0 && id_beg>0 && id_beg<id_end){ bool ok =true; for(int64_t id=id_beg; id<id_end; ++id){ if(Service* service =_load_service(id, path)){ if(_add_service(service)){ service->release(); } else{ service->unload(); service->release(); ok =false; break; } } else{ ok =false; break; } } RangeId* service_id =SafeNew<RangeId>(); service_id->setRange(id_beg, id_end); service_id->setAlgrithm(alg_type); _set_service_id(id_srv, service_id); if(ok){ return id_beg; } else{ unloadService(id_beg); return -1; } } else{ ERROR("load service failed, id invalid"); return -1; } }