diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93c2680 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +webapp/php-common +*.*\~ +*.*~ +*.*\# +*.*# +\#* +\.\#* +~*.* +\#*.* +*.pb.* +CMakeCache.txt +cmake_install.cmake +CMakeFiles +Makefile +server/bin +__pycache__ +*pb2.py +*.pyc +*.out +compile_commands.json +test/test diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..c482482 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,64 @@ +project(test) +cmake_minimum_required(VERSION 2.8) + +set(CMAKE_BUILD_TYPE "Debug") +set(CMAKE_CXX_FLAGS_RELEASE "-std=gnu++11 -fsanitize=address -fno-omit-frame-pointer") +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -std=gnu++11") + +include_directories( + AFTER + ../../a8engine + /usr/include/mysql + /usr/include/jsoncpp + /usr/include/hiredis + ../../ + . +) + +link_directories( + /usr/lib64/mysql + /usr/local/lib +) + +aux_source_directory(../../a8engine/a8 + SRC_LIST +) + +aux_source_directory(../../framework/cpp + SRC_LIST +) + +aux_source_directory(. + SRC_LIST +) + +set(EXECUTABLE_OUTPUT_PATH + ${PROJECT_BINARY_DIR}/ +) + +set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG "_DEBUG") + +add_executable( + test ${SRC_LIST} +) + +# add_custom_target(script_pb_protocol ALL) +# add_custom_command(TARGET script_pb_protocol +# PRE_BUILD +# COMMAND python ../tools/scripts/construct/build_pb.py +# ) +# add_dependencies(test script_pb_protocol) + +target_link_libraries( + test + pthread + mysqlclient + protobuf + rt + crypto + ssl + jsoncpp + curl + hiredis + tinyxml2 +) diff --git a/test/app.cc b/test/app.cc new file mode 100644 index 0000000..2992f5b --- /dev/null +++ b/test/app.cc @@ -0,0 +1,235 @@ +#include "precompile.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "framework/cpp/netmsghandler.h" +#include "framework/cpp/msgqueue.h" +#include "framework/cpp/dbpool.h" + +#include "app.h" + +struct IMMsgNode +{ + unsigned short msgid; + a8::XParams params; + IMMsgNode* next = nullptr; + +}; + +const char* const PROJ_LOG_ROOT = "/data/logs/%s/logs"; +const char* const PROJ_LOG_FILENAME = "log_$pid_%Y%m%d.log"; + +void App::Init(int argc, char* argv[]) +{ + this->argc = argc; + this->argv = argv; + + if (!ParseOpt()) { + terminated = true; + a8::XPrintf("f8test启动失败,缺少-i参数\n", {}); + return; + } + a8::XPrintf("f8test starting instance_id:%d pid:%d\n", {instance_id, getpid()}); + signal(SIGPIPE, SIG_IGN); + + loop_mutex_ = new std::mutex(); + loop_cond_ = new std::condition_variable(); + im_msg_mutex_ = new std::mutex(); + + srand(time(nullptr)); + InitLog(); + a8::Timer::Instance()->Init(); + f8::MsgQueue::Instance()->Init(); + f8::DBPool::Instance()->Init(); + f8::DBPool::Instance()->SetThreadNum(10); + + a8::UdpLog::Instance()->Info("f8test starting instance_id:%d pid:%d", {instance_id, getpid()}); +} + +void App::UnInit() +{ + if (terminated) { + return; + } + f8::DBPool::Instance()->UnInit(); + f8::MsgQueue::Instance()->UnInit(); + a8::Timer::Instance()->UnInit(); + UnInitLog(); + + delete im_msg_mutex_; + im_msg_mutex_ = nullptr; + delete loop_cond_; + loop_cond_ = nullptr; + delete loop_mutex_; + loop_mutex_ = nullptr; +} + +int App::Run() +{ + if (terminated) { + return 0; + } + int ret = 0; + a8::UdpLog::Instance()->Info("f8test running", {}); + while (!terminated) { + #if 0 + a8::tick_t begin_tick = a8::XGetTickCount(); + #endif + QuickExecute(); + SlowerExecute(); + #if 0 + a8::tick_t end_tick = a8::XGetTickCount(); + #endif + Schedule(); + } + return ret; +} + +void App::AddIMMsg(unsigned short imcmd, a8::XParams params) +{ + IMMsgNode *p = new IMMsgNode; + p->msgid = imcmd; + p->params = params; + p->next = nullptr; + im_msg_mutex_->lock(); + if (im_bot_node_) { + im_bot_node_->next = p; + im_bot_node_ = p; + } else { + im_top_node_ = p; + im_bot_node_ = p; + } + im_msg_mutex_->unlock(); + NotifyLoopCond(); +} + +void App::QuickExecute() +{ + ProcessIMMsg(); + a8::Timer::Instance()->Update(); +} + +void App::SlowerExecute() +{ +} + +void App::NotifyLoopCond() +{ + std::unique_lock lk(*loop_mutex_); + loop_cond_->notify_all(); +} + +void App::Schedule() +{ + std::unique_lock lk(*loop_mutex_); + if (!HasTask()) { + int sleep_time = a8::Timer::Instance()->GetIdleableMillSeconds(); + loop_cond_->wait_for(lk, std::chrono::milliseconds(sleep_time)); + } +} + +bool App::HasTask() +{ + { + if (!im_work_node_) { + im_msg_mutex_->lock(); + if (!im_work_node_ && im_top_node_) { + im_work_node_ = im_top_node_; + im_top_node_ = nullptr; + im_bot_node_ = nullptr; + } + im_msg_mutex_->unlock(); + } + if (im_work_node_) { + return true; + } + } + return false; +} + +void App::ProcessIMMsg() +{ + if (!im_work_node_ && im_top_node_) { + im_msg_mutex_->lock(); + im_work_node_ = im_top_node_; + im_top_node_ = nullptr; + im_bot_node_ = nullptr; + im_msg_mutex_->unlock(); + } + while (im_work_node_) { + IMMsgNode *pdelnode = im_work_node_; + switch (im_work_node_->msgid) { + case f8::IM_SysMsgQueue: + { + const a8::XParams* param = (const a8::XParams*)pdelnode->params.param1.GetUserData(); + f8::MsgQueue::Instance()->ProcessMsg(pdelnode->params.sender.GetInt(), + *param + ); + delete param; + } + break; + } + im_work_node_ = im_work_node_->next; + delete pdelnode; + } +} + +void App::InitLog() +{ + std::string filename_fmt = PROJ_LOG_FILENAME; + if (getenv("is_dev_env")) { + a8::ReplaceString(filename_fmt, "$pid", a8::XValue(0)); + } else { + a8::ReplaceString(filename_fmt, "$pid", a8::XValue(getpid())); + } + + a8::MkDir(a8::Format(PROJ_ROOT, {PROJ_NAME})); + a8::MkDir(a8::Format(PROJ_LOG_ROOT, {PROJ_NAME})); + a8::UdpLog::Instance()->SetLogFileName(a8::Format(PROJ_LOG_ROOT, {PROJ_NAME}) + "/" + filename_fmt); + a8::UdpLog::Instance()->Init(); +} + +void App::UnInitLog() +{ + a8::UdpLog::Instance()->UnInit(); +} + +bool App::ParseOpt() +{ + int ch = 0; + while ((ch = getopt(argc, argv, "i:")) != -1) { + switch (ch) { + case 'i': + { + instance_id = a8::XValue(optarg); + } + break; + } + } + return instance_id > 0; +} + +a8::XParams* App::AddContext(long long context_id) +{ + context_hash_[context_id] = a8::XParams(); + return GetContext(context_id); +} + +void App::DelContext(long long context_id) +{ + context_hash_.erase(context_id); +} + +a8::XParams* App::GetContext(long long context_id) +{ + auto itr = context_hash_.find(context_id); + return itr != context_hash_.end() ? &(itr->second) : nullptr; +} diff --git a/test/app.h b/test/app.h new file mode 100644 index 0000000..df1651a --- /dev/null +++ b/test/app.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +struct IMMsgNode; +class App : public a8::Singleton +{ + private: + App() {}; + friend class a8::Singleton; + + public: + + void Init(int argc, char* argv[]); + void UnInit(); + + int Run(); + + void AddIMMsg(unsigned short imcmd, a8::XParams params); + + void NotifyLoopCond(); + + a8::XParams* AddContext(long long context_id); + void DelContext(long long context_id); + a8::XParams* GetContext(long long context_id); + +private: + void QuickExecute(); + void SlowerExecute(); + void Schedule(); + bool HasTask(); + + void ProcessIMMsg(); + + void InitLog(); + void UnInitLog(); + + bool ParseOpt(); + + public: + int argc = 0; + char** argv = nullptr; + volatile bool terminated = false; + +public: + int instance_id = 0; + + private: + std::mutex *loop_mutex_ = nullptr; + std::condition_variable *loop_cond_ = nullptr; + + std::mutex* im_msg_mutex_ = nullptr; + IMMsgNode* im_top_node_ = nullptr; + IMMsgNode* im_bot_node_ = nullptr; + IMMsgNode* im_work_node_ = nullptr; + + std::map context_hash_; + +}; diff --git a/test/constant.h b/test/constant.h new file mode 100644 index 0000000..ead1121 --- /dev/null +++ b/test/constant.h @@ -0,0 +1,12 @@ +#pragma once + +enum InnerMesssage_e +{ + IM_Begin = 100, + IM_ClientSocketDisconnect, + IM_ExecGM, + IM_ExecAsyncSql +}; + +const char* const PROJ_NAME = "f8test"; +const char* const PROJ_ROOT = "/data/logs/%s"; diff --git a/test/main.cc b/test/main.cc new file mode 100644 index 0000000..7dffbf1 --- /dev/null +++ b/test/main.cc @@ -0,0 +1,11 @@ +#include "precompile.h" +#include "app.h" + +int main(int argc, char* argv[]) +{ + int exitcode = 0; + App::Instance()->Init(argc, argv); + exitcode = App::Instance()->Run(); + App::Instance()->UnInit(); + return exitcode; +} diff --git a/test/precompile.h b/test/precompile.h new file mode 100644 index 0000000..f50bb88 --- /dev/null +++ b/test/precompile.h @@ -0,0 +1,19 @@ +#pragma once + + +#include +#include + +#include "constant.h" +#include "types.h" + +namespace google +{ + namespace protobuf + { + class Message; + } +} + +#include "framework/cpp/types.h" +#include "framework/cpp/protoutils.h" diff --git a/test/types.h b/test/types.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/test/types.h @@ -0,0 +1 @@ +#pragma once