└── LogLibrary ├── makefile ├── test ├── timestamp_test.cpp ├── asynLog_test.cpp └── condtion_test.cpp ├── logFile.h ├── asynLog_test.cpp ├── mutex.h ├── condtion.h ├── logFile.cpp ├── timestamp.h ├── asynLog.h ├── fixBuffer.h └── asynLog.cpp /LogLibrary/makefile: -------------------------------------------------------------------------------- 1 | CC = clang++ -std=c++11 2 | CGLAGS = -Wall -g 3 | LDFLAGS = -pthread 4 | hehe:asynLog_test.o asynLog.o logFile.o 5 | ${CC} ${CGLAGS} -o hehe asynLog_test.o asynLog.o logFile.o ${LDFLAGS} && rm *.o 6 | asynLog_test.o:asynLog.h 7 | ${CC} ${CGLAGS} -c asynLog_test.cpp 8 | asynLog.o:asynLog.h logFile.h fixBuffer.h 9 | ${CC} ${CGLAGS} -c asynLog.cpp 10 | logFile.o:logFile.h 11 | ${CC} ${CGLAGS} -c logFile.cpp 12 | .PHONY:clean 13 | clean: 14 | rm *.o 15 | -------------------------------------------------------------------------------- /LogLibrary/test/timestamp_test.cpp: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: timestamp_test.cpp 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月23日 星期三 09时28分38秒 7 | =======================================================*/ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "timestamp.h" 13 | #include 14 | #include 15 | int main(int argc,char **argv) 16 | { 17 | struct tm time = netlib::Timestamp().now(); 18 | netlib::Timestamp t; 19 | char *p = t.toStringTime(); 20 | printf("%s\n%d\n",p,strlen(p)); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /LogLibrary/test/asynLog_test.cpp: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: asynLog_test.cpp 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月26日 星期六 16时39分03秒 7 | =======================================================*/ 8 | 9 | #include 10 | #include "asynLog.h" 11 | #include 12 | #include 13 | #include 14 | int main(int argc,char **argv) 15 | { 16 | netlib::AsynLog log(1000); 17 | char s[100] = "hello\n"; 18 | log.setLevel(netlib::LogLevel::ALL); 19 | for(int i = 0; i < 2; i++) 20 | { 21 | 22 | log.append(s,strlen(s),netlib::LogLevel::INFO); 23 | } 24 | log.stop(); 25 | sleep(1000); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /LogLibrary/logFile.h: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: logFile.h 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月26日 星期六 14时57分54秒 7 | =======================================================*/ 8 | #ifndef LOG_FILE_H_ 9 | #define LOG_FILE_H_ 10 | namespace netlib 11 | { 12 | class LogFile 13 | { 14 | public: 15 | LogFile(int rollSize); 16 | ~LogFile(); 17 | //往磁盘里添加消息 18 | void append(char *log,int len); 19 | //滚动文件 20 | void rollFile(int curLen); 21 | 22 | private: 23 | int rollSize_; //文件滚动大小 24 | int fd_; 25 | int fillSize_; //当前文件填充大小 26 | int fileNumbers_; //已有文件数量 27 | }; 28 | } 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /LogLibrary/asynLog_test.cpp: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: asynLog_test.cpp 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月26日 星期六 16时39分03秒 7 | =======================================================*/ 8 | 9 | #include 10 | #include "asynLog.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | netlib::AsynLog log(1024*1024*1024); 17 | 18 | void func(void) 19 | { 20 | char s[100] = "hello\n"; 21 | log.setLevel(netlib::LogLevel::ALL); 22 | while(true) 23 | { 24 | log.append(s,netlib::LogLevel::INFO); 25 | } 26 | } 27 | 28 | int main(int argc,char **argv) 29 | { 30 | std::thread t1(func); 31 | std::thread t2(func); 32 | std::thread t3(func); 33 | std::thread t4(func); 34 | t1.join(); 35 | t2.join(); 36 | t3.join(); 37 | t4.join(); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /LogLibrary/test/condtion_test.cpp: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: condtion_test.cpp 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月24日 星期四 12时44分38秒 7 | =======================================================*/ 8 | #include "condtion.h" 9 | #include "mutex.h" 10 | #include 11 | #include 12 | #include 13 | 14 | int sum = 0; 15 | netlib::Mutex mutex; 16 | netlib::Condtion condtion(mutex.getMutex()); 17 | void work(int n) 18 | { 19 | while(1) 20 | { 21 | mutex.lock(); 22 | sum++; 23 | printf("%d:被加到%d\n",n,sum); 24 | mutex.unlock(); 25 | 26 | } 27 | } 28 | 29 | int main(void) 30 | { 31 | std::thread t1(work,1); 32 | std::thread t2(work,2); 33 | std::thread t3(work,3); 34 | 35 | while(1) 36 | { 37 | mutex.lock(); 38 | condtion.wait(); 39 | while(sum > 0) 40 | { 41 | sum--; 42 | } 43 | 44 | printf("sum被减为sum = %d\n",sum); 45 | mutex.unlock(); 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /LogLibrary/mutex.h: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: mutex.h 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月23日 星期三 11时21分53秒 7 | =======================================================*/ 8 | #ifndef MUTEX_H_ 9 | #define MUTEX_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | namespace netlib 16 | { 17 | class Mutex 18 | { 19 | public: 20 | Mutex() 21 | { 22 | pthread_mutex_init(&mutex_,NULL); 23 | } 24 | ~Mutex() 25 | { 26 | pthread_mutex_destroy(&mutex_); 27 | } 28 | 29 | void lock() //上锁 30 | { 31 | int ret = pthread_mutex_lock(&mutex_); 32 | printf("hello = %p\n",&mutex_); 33 | assert(ret == 0); 34 | } 35 | 36 | void unlock() //解锁 37 | { 38 | int ret = pthread_mutex_unlock(&mutex_); 39 | assert(ret == 0); 40 | } 41 | 42 | pthread_mutex_t *getMutex() //获得互斥锁 43 | { 44 | return &mutex_; 45 | } 46 | private: 47 | pthread_mutex_t mutex_; 48 | }; 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /LogLibrary/condtion.h: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: cond.h 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月23日 星期三 12时20分02秒 7 | =======================================================*/ 8 | 9 | #ifndef CONDTION_H_ 10 | #define CONDTION_H_ 11 | 12 | //#include "mutex.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace netlib 19 | { 20 | class Condtion 21 | { 22 | public: 23 | Condtion(pthread_mutex_t *mutex) 24 | :mutex_(mutex) 25 | { 26 | pthread_cond_init(&cond_,NULL); 27 | } 28 | ~Condtion() 29 | { 30 | pthread_cond_destroy(&cond_); 31 | } 32 | 33 | void wait() //条件等待 34 | { 35 | int ret = pthread_cond_wait(&cond_,mutex_); 36 | assert(ret == 0); 37 | } 38 | 39 | void notify() //唤醒 40 | { 41 | int ret = pthread_cond_signal(&cond_); 42 | assert(ret == 0); 43 | } 44 | 45 | void notifyAll() //唤醒全部 46 | { 47 | int ret = pthread_cond_broadcast(&cond_); 48 | assert(ret == 0); 49 | } 50 | private: 51 | pthread_mutex_t *mutex_; 52 | pthread_cond_t cond_; 53 | }; 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /LogLibrary/logFile.cpp: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: logFile.cpp 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月26日 星期六 15时12分35秒 7 | =======================================================*/ 8 | #include "logFile.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace netlib; 18 | 19 | LogFile::LogFile(int rollSize) 20 | :rollSize_(rollSize), 21 | fillSize_(0), 22 | fileNumbers_(1) 23 | { 24 | fd_ = open("/home/shreck/log/mylog.log",O_WRONLY | O_APPEND | O_CREAT,S_IWUSR | S_IRUSR | S_IXUSR); 25 | assert(fd_ > 0); 26 | } 27 | 28 | LogFile::~LogFile() 29 | { 30 | close(fd_); 31 | } 32 | 33 | void LogFile::append(char *log,int len) 34 | { 35 | int ret = write(fd_,log,len); 36 | rollFile(ret); 37 | assert(ret == len); 38 | } 39 | 40 | void LogFile::rollFile(int curLen) 41 | { 42 | fillSize_ += curLen; 43 | if(fillSize_ >= rollSize_) 44 | { 45 | printf("1G满了\n"); 46 | //置0fillSize_ 47 | fillSize_ = 0; 48 | char command[80]; 49 | snprintf(command,sizeof(command),"mv /home/shreck/log/mylog.log /home/shreck/log/mylog%d.log",fileNumbers_); 50 | fileNumbers_++; 51 | //改当前文件名为fileName 52 | system(command); 53 | //重新创建一个mylog.log文件 54 | fd_ = open("/home/shreck/log/mylog.log",O_WRONLY | O_APPEND | O_CREAT,S_IWUSR | S_IRUSR | S_IXUSR); 55 | assert(fd_ > 0); 56 | } 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /LogLibrary/timestamp.h: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: timestamp.h 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月23日 星期三 08时33分16秒 7 | =======================================================*/ 8 | #ifndef TIMESTAMP_H_ 9 | #define TIMESTAMP_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace netlib 19 | { 20 | class Timestamp 21 | { 22 | public: 23 | Timestamp() 24 | { 25 | 26 | } 27 | ~Timestamp() 28 | { 29 | 30 | } 31 | 32 | static struct tm now(void) //获取当前tm格式的时间 33 | { 34 | struct timeval tv; 35 | struct tm time; 36 | 37 | gettimeofday(&tv,NULL); //获取微妙,秒值 38 | localtime_r(&tv.tv_sec,&time); //将s转换为tm格式 39 | time.tm_year += 1900; 40 | time.tm_mon += 1; 41 | return time; 42 | } 43 | 44 | static timeval getTime(void) 45 | { 46 | struct timeval tv; 47 | 48 | gettimeofday(&tv,NULL); 49 | return tv; 50 | } 51 | 52 | char *toStringTime(void) //将时间转化为字符串并返回 53 | { 54 | struct tm time; 55 | bzero(str_,sizeof(str_)); 56 | time = now(); 57 | snprintf(str_,sizeof(str_),"%d-%d-%d %d:%d:%d ",time.tm_year,time.tm_mon,time.tm_mday,time.tm_hour,time.tm_min,time.tm_sec); 58 | return str_; 59 | } 60 | 61 | static int getTimeDiff(timeval v1,timeval v2) //获得俩时间的时间差,返回值为微妙 62 | { 63 | int t; 64 | t = v1.tv_sec*1000000 + v1.tv_usec - v2.tv_sec*1000000 - v2.tv_usec; 65 | t = abs(t); 66 | return t; 67 | } 68 | 69 | private: 70 | char str_[200]; 71 | }; 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /LogLibrary/asynLog.h: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: asynLog.h 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月24日 星期四 17时33分26秒 7 | =======================================================*/ 8 | #ifndef ASYNLOG_H_ 9 | #define ASYNLOG_H_ 10 | 11 | #include 12 | #include "fixBuffer.h" 13 | #include "timestamp.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace netlib 21 | { 22 | enum LogLevel 23 | { 24 | OFF, //关闭所有日志记录 25 | FATAL, //导致程序退出的错误 26 | ERROE, //发生了错误但不影响系统运行 27 | WARN, //会出现潜在的错误情形 28 | INFO, //系统发生了那些事情 29 | DEBUG, //调试程序有关的信息 30 | ALL, //输出所有日志记录 31 | }; 32 | class AsynLog 33 | { 34 | public: 35 | AsynLog(int roolSize); 36 | ~AsynLog(); 37 | void append(char *logline,LogLevel level); //添加日志行 38 | void setLevel(LogLevel level); //设置日志的水平 39 | void stop(void); //关闭日志 40 | private: 41 | void threadFunc(void); //线程函数 42 | bool aboveLevel(LogLevel level); //判断某条日志等级是否超过我们所设的level 43 | void writeBuffer(const char* logline,int len); //将日志内容写入buffer中 44 | std::string toStringForLevel(LogLevel level); //将对应的level转化为字符串 45 | 46 | int rollSize_; //文件达到多大时滚动 47 | bool running_; 48 | std::unique_ptr currentBuffer_; //当前buffer 49 | std::unique_ptr nextBuffer_; //备用buffer 50 | std::vector> buffers_; //保存buffer的vector 51 | std::thread acceptThread_; //后台接受数据的线程 52 | std::mutex mutex_; //互斥变量 53 | std::condition_variable_any condition_; //条件变量 54 | Timestamp timestamp_; //时间戳 55 | LogLevel currentLevel_; //当前日志等级 56 | }; 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /LogLibrary/fixBuffer.h: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: fixBuffer.h 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月24日 星期四 17时02分09秒 7 | =======================================================*/ 8 | #ifndef FIX_BUFFER_H_ 9 | #define FIX_BUFFER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | namespace netlib 18 | { 19 | class FixBuffer 20 | { 21 | public: 22 | FixBuffer() 23 | :buffer_(1024*1024*4) //初始化大小为4M 24 | { 25 | readableIndex_ = 0; 26 | writeableIndex_ = 0; 27 | } 28 | ~FixBuffer() 29 | { 30 | 31 | } 32 | int readableSize(void) //可读字节数 33 | { 34 | return writeableIndex_ - readableIndex_; 35 | } 36 | 37 | int writeableSize(void) //可写字节数 38 | { 39 | return buffer_.size() - writeableIndex_; 40 | } 41 | 42 | void append(const char *data,int len) //添加数据到buffer中 43 | { 44 | std::copy(data,data + len,getWritePeek()); 45 | moveWriteIndex(len); 46 | } 47 | 48 | char *getReadPeek(void) //获得读位置的指针 49 | { 50 | return begin() + readableIndex_; 51 | } 52 | 53 | char *getWritePeek(void) //获得写位置的指针 54 | { 55 | return begin() + writeableIndex_; 56 | } 57 | 58 | 59 | void moveWriteIndex(int len) //移动可写下标 60 | { 61 | writeableIndex_ = writeableIndex_ + len; 62 | } 63 | 64 | void resetBuffer(void) //重置buffer 65 | { 66 | readableIndex_ = 0; 67 | writeableIndex_ = 0; 68 | } 69 | 70 | private: 71 | char *begin() 72 | { 73 | return &*buffer_.begin(); 74 | } 75 | 76 | 77 | std::vector buffer_; 78 | int readableIndex_; 79 | int writeableIndex_; 80 | 81 | }; 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /LogLibrary/asynLog.cpp: -------------------------------------------------------------------------------- 1 | /*====================================================== 2 | > File Name: asynLog.cpp 3 | > Author: MiaoShuai 4 | > E-mail: 5 | > Other : 6 | > Created Time: 2015年12月24日 星期四 18时48分21秒 7 | =======================================================*/ 8 | #include "asynLog.h" 9 | #include "logFile.h" 10 | #include "timestamp.h" 11 | #include 12 | #include 13 | #include 14 | #include "fixBuffer.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace netlib; 21 | 22 | AsynLog::AsynLog(int rollSize) 23 | :rollSize_(rollSize), 24 | running_(true), 25 | currentBuffer_(new FixBuffer()), 26 | nextBuffer_(new FixBuffer()), 27 | acceptThread_(std::bind(&AsynLog::threadFunc,this)) 28 | { 29 | } 30 | 31 | AsynLog::~AsynLog() 32 | { 33 | stop(); 34 | } 35 | 36 | void AsynLog::setLevel(LogLevel level) 37 | { 38 | currentLevel_ = level; 39 | } 40 | 41 | bool AsynLog::aboveLevel(LogLevel level) 42 | { 43 | return level <= currentLevel_; 44 | } 45 | 46 | 47 | void AsynLog::append(char *logline,LogLevel level) 48 | { 49 | if(aboveLevel(level)) //如果level超过所设等级 50 | { 51 | std::lock_guard guard(mutex_); 52 | //与时间以及线程id等字符串连接 53 | std::string log1(logline); //日志内容 54 | std::string log2(timestamp_.toStringTime());//获得时间戳的字符串 55 | char log3[30]; 56 | snprintf(log3,sizeof(log3),"threadid[%lu]: ",pthread_self());//获得线程id的字符串 57 | std::string log4(toStringForLevel(level)); //获得等级对应的字符串 58 | log2 = log2 + log3 + log4 + log1; 59 | writeBuffer(log2.c_str(),log2.size()); //写入buffer 60 | } 61 | } 62 | 63 | 64 | void AsynLog::writeBuffer(const char *logline,int len) 65 | { 66 | if(currentBuffer_->writeableSize() >= len) //如果当前buffer空间足 67 | { 68 | currentBuffer_->append(logline,len); 69 | } 70 | else 71 | { 72 | buffers_.push_back(std::move(currentBuffer_)); //返回指针,自己变为空 73 | 74 | if(nextBuffer_) 75 | { 76 | currentBuffer_ = std::move(nextBuffer_); //将nextBuffer_的控制权交给currentBuffer_ 77 | } 78 | else 79 | { 80 | currentBuffer_.reset(new FixBuffer()); //申请一块新的buffer 81 | } 82 | 83 | currentBuffer_->append(logline,len); 84 | condition_.notify_one(); //唤醒后台线程 85 | } 86 | } 87 | 88 | std::string AsynLog::toStringForLevel(LogLevel level) 89 | { 90 | switch(level) 91 | { 92 | case LogLevel::OFF: 93 | return std::string("OFF ");break; 94 | case LogLevel::FATAL: 95 | return std::string("FATAL ");break; 96 | case LogLevel::ERROE: 97 | return std::string("ERROE ");break; 98 | case LogLevel::WARN: 99 | return std::string("WARN ");break; 100 | case LogLevel::INFO: 101 | return std::string("INFO ");break; 102 | case LogLevel::DEBUG: 103 | return std::string("DEBUG ");break; 104 | case LogLevel::ALL: 105 | return std::string("ALL ");break; 106 | default:return std::string("UNKNOWN "); 107 | } 108 | return NULL; 109 | } 110 | 111 | void AsynLog::stop(void) 112 | { 113 | if(running_) 114 | { 115 | running_ = false; 116 | acceptThread_.join(); //等待后台进程退出 117 | printf("日志系统已关闭\n"); 118 | } 119 | } 120 | 121 | void AsynLog::threadFunc(void) 122 | { 123 | std::unique_ptr newBuffer1(new FixBuffer); 124 | std::unique_ptr newBuffer2(new FixBuffer); 125 | std::vector> buffersToWrite; 126 | LogFile output(rollSize_); 127 | buffersToWrite.reserve(16); 128 | while(running_) 129 | { 130 | { 131 | std::lock_guard guard(mutex_); //临界区加锁 132 | if(buffers_.empty()) //如果buffers_为空 133 | { 134 | condition_.wait_for(mutex_,std::chrono::seconds(3)); 135 | } 136 | buffers_.push_back(std::move(currentBuffer_)); 137 | currentBuffer_ = std::move(newBuffer1); 138 | buffersToWrite.swap(buffers_); //交换俩个容器 139 | if(!nextBuffer_) 140 | { 141 | nextBuffer_ = std::move(newBuffer2); 142 | } 143 | 144 | } 145 | assert(!buffersToWrite.empty()); 146 | 147 | if(buffersToWrite.size() > 25) 148 | { 149 | //日志异常 150 | } 151 | 152 | //将buffer中的内容写进文件中 153 | for(int i = 0; i < buffersToWrite.size(); i++) 154 | { 155 | output.append(buffersToWrite[i]->getReadPeek(),buffersToWrite[i]->readableSize()); 156 | } 157 | 158 | if(buffersToWrite.size() > 2) 159 | { 160 | buffersToWrite.resize(2); 161 | } 162 | 163 | if(!newBuffer1) 164 | { 165 | assert(!buffersToWrite.empty()); 166 | newBuffer1 = std::move(buffersToWrite[0]); 167 | newBuffer1->resetBuffer(); //重置buffer 168 | } 169 | 170 | if(!newBuffer2) 171 | { 172 | assert(!buffersToWrite.empty()); 173 | newBuffer2 = std::move(buffersToWrite[1]); 174 | newBuffer2->resetBuffer(); 175 | } 176 | 177 | buffersToWrite.clear(); 178 | } 179 | } 180 | --------------------------------------------------------------------------------