Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/core/workers/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

tmp
*.stackdump

35 changes: 35 additions & 0 deletions src/core/workers/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
1. Build logworkers link

target:
link/logworkers.o

command:
e.g.
$ make Container_Type=-DLOG_PRIORITY_QUEUE
$ # Container_Type=-DLOG_PRIORITY_QUEUE # or '-DLOG_LOCKFREE_QUEUE'

tips:
-DLOG_PRIORITY_QUEUE
Log container using 'priority queue'.
by default, it will output priority the 'FATAL' level logs
-DLOG_LOCKFREE_QUEUE
Log container using 'lockfree queue'

2. Build demo

target:
./demo/bin/test_logworkers.static
./demo/bin/test_logworkers

commad:
e.g.
$ cd ./demo
$ make Container_Type=-DLOG_PRIORITY_QUEUE PYTHON_INCLUDE=/usr/include/python2.7 PYTHON_LIB_PATH=/usr/lib PYTHON_LIB=-lpython2.7
tips:
PYTHON_LIB_PATH is the path to python library files, libpython2.7.so libpython2.7.a ...
default path: /usr/lib
PYTHON_LIB is '-l' option of gcc, -lpython2.7, -lpython2.7.dll ...
please using -lpython2.7.dll on Cygwin.



41 changes: 41 additions & 0 deletions src/core/workers/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
CC = gcc
XX = g++
RM = rm -rf

PWD = $(shell pwd)
ROOT = $(PWD)/../
LINK = ./link

LOG_SRC = $(ROOT)/log

CFLAGS = -Wall -D_REENTRANT $(Container_Type) -g -std=gnu++0x # win32: -std=c++11


INCLUDE = -I$(ROOT)/../../contrib/boost/boost_1_57_0/ \
-I$(ROOT)/ -I.
#STDLIB = -stdlib=libc++ # win32

all: init TARGET

init:
ifndef Container_Type
$(info [ err] Container_Type not set!)
$(info [info] e.g )
$(info [info] $$ Container_Type=-DLOG_PRIORITY_QUEUE # or '-DLOG_LOCKFREE_QUEUE')
$(info [info] $$ make ... Container_Type=$$Container_Type ...)
$(error error)
endif
[ -d '$(LINK)' ] || mkdir $(LINK)
cd $(LOG_SRC); make loglib Container_Type=$(Container_Type)

TARGET: $(LINK)/logworkers.o

$(LINK)/%.o: %.c
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
$(LINK)/%.o: %.cpp
$(XX) $(CFLAGS) $(STDLIB) $(INCLUDE) -c $< -o $@


clean:
$(RM) $(LINK)

4 changes: 4 additions & 0 deletions src/core/workers/demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bin
~tmp
*.stackdump

79 changes: 79 additions & 0 deletions src/core/workers/demo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
CC = gcc
XX = g++
RM = rm -rf

PWD = $(shell pwd)
ROOT = $(PWD)/../../
TMP = ./~tmp
BIN = ./bin

WORKERS_SRC = $(ROOT)/workers
LOGROTATE_SRC = $(ROOT)/logrotate
PYTHON_SRC = $(ROOT)/python
EXCEPT_SRC = $(ROOT)/except
LOG_SRC = $(ROOT)/log
LOG_LIB_DIR = $(LOG_SRC)/lib

CFLAGS = -Wall -D_REENTRANT $(Container_Type) -g -std=gnu++0x # win32: -std=c++11


INCLUDE = -I$(ROOT)/../../contrib/boost/boost_1_57_0/ -I$(ROOT)
#STDLIB = -stdlib=libc++ # win32

BOOST_LINK_DIR = $(ROOT)/boost_build/link
BOOST_LINK = $(BOOST_LINK_DIR)/sysprebuild.o \
$(BOOST_LINK_DIR)/dateprebuild.o \
$(BOOST_LINK_DIR)/tprebuild.o

ALL_LINK = $(WORKERS_SRC)/link/logworkers.o \
$(LOGROTATE_SRC)/link/logrotate.o \
$(PYTHON_SRC)/lib/libpyfunc.a \
$(EXCEPT_SRC)/link/except.o \
$(BOOST_LINK)

LIBPATH = -L$(LOG_LIB_DIR) -L$(PYTHON_SRC)/lib
LIBS += $(LIBPATH) -llog $(PYTHON_LIB) -lpthread -lrt -ldl -lutil -lz

all: init TARGET

init:
ifndef Container_Type
$(info [ err] Container_Type not set!)
$(info [info] e.g )
$(info [info] $$ Container_Type=-DLOG_PRIORITY_QUEUE # or '-DLOG_LOCKFREE_QUEUE')
$(info [info] $$ make ... Container_Type=$$Container_Type ...)
$(error error)
endif
ifndef PYTHON_INCLUDE
$(info PYTHON_INCLUDE not set !)
$(info e.g. $$ make ... PYTHON_INCLUDE=/usr/include/python2.7 ...)
$(error error)
endif
ifndef PYTHON_LIB
$(info [ err] PYTHON_LIB not set !)
$(info [info] e.g. $$ make ... PYTHON_LIB=-lpython2.7 ...)
$(error error)
endif
[ -d '$(TMP)' ] || mkdir $(TMP)
[ -d '$(BIN)' ] || mkdir $(BIN)
cd $(WORKERS_SRC); make Container_Type=$(Container_Type) USE_LOCK=-DLOG_USE_LOCK
cd $(LOGROTATE_SRC); make PYTHON_INCLUDE=$(PYTHON_INCLUDE)


TARGET: $(BIN)/test_logworkers $(BIN)/test_logworkers.static

$(BIN)/test_logworkers: $(TMP)/test_logworkers.o $(ALL_LINK)
$(XX) $^ -o $@ $(LIBS)
$(BIN)/test_logworkers.static: $(TMP)/test_logworkers.o $(ALL_LINK)
$(XX) $^ -o $@ -static $(LIBS)

$(TMP)/%.o: %.c
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
$(TMP)/%.o: %.cpp
$(XX) $(CFLAGS) $(STDLIB) $(INCLUDE) -c $< -o $@


clean:
$(RM) $(TMP) $(BIN)
cd $(LOG_SRC); make clean

81 changes: 81 additions & 0 deletions src/core/workers/demo/test_logworkers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include <iostream>
#include "workers/logworkers.h"

void produce_log() {
loginfo("thread id:[" << boost::this_thread::get_id() << "] Start..." );
for (int i = 0; i < 5; ++i) {
logwarn("test...");
}
}

void test() {
using namespace std;
bool ret = LogOutput_t::get_instance().bind(cout);
cout << boolalpha << ret << endl;

Workers<LogWorkers>& workers = LogWorkers::get_mutable_instance();
//workers.start(2);
workers.start(3, true);
boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
workers.interrupt_all(/*false*/);
//boost::this_thread::sleep_for(chrono::milliseconds(100));
}

int main(int argc, char** argv) {
produce_log();
test();
return 0;
}
///////////////////////////////////////////////////

//#include "store.h"
//
//class rw_data {
// private:
// int m_x;
// shared_mutex rw_mu;
// public:
// rw_data() : m_x(0) {}
// void write() {
// unique_lock<shared_mutex> ul(rw_mu);
// ++m_x;
// }
// void read(int *x) {
// shared_lock<shared_mutex> sl(rw_mu);
// *x = m_x;
// }
//};
//void writer(rw_data &d) {
// for (int i = 0; i < 20; ++i) {
// this_thread::sleep_for(chrono::milliseconds(10));
// d.write();
// }
//}
//mutex io_mu;
//void reader(rw_data &d) {
// int x;
// for (int i = 0; i < 10; ++i) {
// this_thread::sleep_for(chrono::milliseconds(5));
// d.read(&x);
// mutex::scoped_lock lock(io_mu);
// cout << "reader: " << x << endl;
// }
//}
//void test2() {
// rw_data d;
// thread_group pool;
// pool.create_thread(boost::bind(writer, boost::ref(d)));
// pool.create_thread(boost::bind(writer, boost::ref(d)));
//
// pool.create_thread(boost::bind(reader, boost::ref(d)));
// pool.create_thread(boost::bind(reader, boost::ref(d)));
// pool.create_thread(boost::bind(reader, boost::ref(d)));
// pool.create_thread(boost::bind(reader, boost::ref(d)));
//
// pool.join_all();
//}
//
//int main(int argc, char** argv) {
// test2();
// return 0;
//}
50 changes: 50 additions & 0 deletions src/core/workers/logworkers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "workers/logworkers.h"
#include "log/logoutput.h" // is used in the function process()
#include <sstream>
#include <ctime>
using namespace std;

/* 处理中断时使用的输出流, 初始值为std::cout */
/*static*/ostream& LogWorkers::m_interrupt_os = cout;
/* 处理日志转储所使用的Logrotate对象, 初始值为NULL */
/*static*/Logrotate* LogWorkers::logrt = NULL;

// 重写三个虚函数
void LogWorkers::prepare() {
loginfo("Now start a Workers thread(id:"
<< boost::this_thread::get_id()
<< ", module:LogWorkers)!");
this->val = std::make_shared<LogVal>();
}


void LogWorkers::process() {
// 因为本身是从日志仓库里输出日志, 所以这里不能再往日志仓库扔东西
LogOutput_t::get_instance().output_once(this->val);

// 尝试日志转储
if (logrt) {
logrt->action();
}
}

void LogWorkers::interruption_respond() {
// 因为本身是从日志仓库里输出日志, 所以这里不能再往日志仓库扔东西
time_t timer = time(NULL);
string cur_time = asctime(localtime(&timer));
cur_time.pop_back();
ostringstream oss;
oss << cur_time << " [WARNING]: Workers thread(id:"
<< boost::this_thread::get_id() << ", module:LogWorkers) is interrupted!"
<< " [" << __FILE__ << ':' << __LINE__ << ']' << std::endl;

// 安全输出到m_interrupt_os
auto plock = LogOutput_t::get_instance().get_lock(m_interrupt_os);
if (plock) {
LogOutput_t::scoped_lock lock(m_interrupt_os, *plock);
m_interrupt_os << oss.str();
}
else {
m_interrupt_os << oss.str();
}
}
88 changes: 88 additions & 0 deletions src/core/workers/logworkers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#ifndef LOGWORKERS_H
#define LOGWORKERS_H
/*
* LogWorkers 类 (工种: 日志输出)
*
* 1. 说明: 对日志输出的操作模块, 继承自Workers抽象类,单件实现
* 2. 原型: class LogWorkers : public Workers<LogWorkers>;
* 3. 摘要:
* 1. 3个私有重写方法:
* 1. virtual void prepare();
* 进入流程循环之前的处理函数, 用于输出进程信息和标识所在模块
* 2. virtual void process(void);
* 一个(次)工作流程
* 3. virtual void interruption_respond();
* 对于工作线程中断后的响应函数, 用于将错误信息及所在模块标识
* 输出到m_interrupt_os. 其中操作m_interrupt_os时使用了LogOut
* 中的互斥锁,避免线程冲突.
* 2. 2个公有静态成员:
* 1. static std::ostream& m_interrupt_os;
* 处理中断时使用的输出流, 会在interruption_respond()中被使用,
* 初始值为std::cout. 可用在GUI编程时对输出流重新赋值以满足需求.
*
* 2. static Logrotate* logrt; // 为NULL时不执行日志转储
* 处理日志转储所使用的Logrotate对象指针, 初始值为NULL
*
* 4. 直接依赖:
* 1. 日志模块, 包括日志生产和LogOutput
* 2. Workers抽象类
* 3. 日志转储模块 Logrotate
*
*/

///////////////////////////////////////////////////////////////////////
//example:
//
// produce_log(); // some loginfo, logwarning or logerr
// bool ret = LogOut::get_mutable_instance().bind(std::cout);
// cout << boolalpha << ret << endl;
//
// Workers<LogWorkers>& workers = LogWorkers::get_mutable_instance();
// //workers.start(2/*, false*/); // waiting...
// workers.start(3, true);
// boost::this_thread::sleep_for(chrono::milliseconds(50));
// workers.interrupt_all(/*false*/); // waiting...
// //boost::this_thread::sleep_for(chrono::milliseconds(100));
//
//a possible output:
//
// true
// Wed Dec 17 20:27:52 2014 [INFO]: produce log thread[id: 0x20000038] starts [main.cpp:8]
// Wed Dec 17 20:27:52 2014 [WARNING]: test... [main.cpp:10]
// Wed Dec 17 20:27:52 2014 [WARNING]: test... [main.cpp:10]
// Wed Dec 17 20:27:52 2014 [WARNING]: test... [main.cpp:10]
// Wed Dec 17 20:27:52 2014 [WARNING]: test... [main.cpp:10]
// Wed Dec 17 20:27:52 2014 [WARNING]: test... [main.cpp:10]
// Wed Dec 17 20:27:52 2014 [INFO]: Now start a Workers thread(id:0x20014ce0, module:LogWorkers)! [logworkers.cpp:14]
// Wed Dec 17 20:27:52 2014 [INFO]: Now start a Workers thread(id:0x20015258, module:LogWorkers)! [logworkers.cpp:14]
// Wed Dec 17 20:27:52 2014 [INFO]: Now start a Workers thread(id:0x200155d8, module:LogWorkers)! [logworkers.cpp:14]
// Wed Dec 17 20:27:52 2014 [WARNING]: Workers thread(id:0x20015258, module:LogWorkers) is interrupted! [logworkers.cpp:30]
// Wed Dec 17 20:27:52 2014 [WARNING]: Workers thread(id:0x20014ce0, module:LogWorkers) is interrupted! [logworkers.cpp:30]
// Wed Dec 17 20:27:52 2014 [WARNING]: Workers thread(id:0x200155d8, module:LogWorkers) is interrupted! [logworkers.cpp:30]
//
///////////////////////////////////////////////////////////////////////

#include <iostream>
#include "workers/workers.h"
//#include "log/logoutput.h" // is used in the function process()
#include "logrotate/logrotate.h"
#include "log/init_simple.h"

class LogWorkers : public Workers<LogWorkers> {
public:
/* 处理中断时使用的输出流, 初始值为std::cout */
static std::ostream& m_interrupt_os;
/* 处理日志转储所使用的Logrotate对象, 初始值为NULL */
static Logrotate* logrt; // 为NULL时不执行日志转储
private:
// 进入流程循环之前的处理函数
virtual void prepare();
// 一个工作流程
virtual void process(void);
// 对于线程中断后的响应函数
virtual void interruption_respond();
LogWorkers& operator=(const LogWorkers&) = delete;
private:
std::shared_ptr<LogVal> val;
};
#endif // LOGWORKERS_H
Loading