static bool __writefile(const void* _data, size_t _len) {
if (NULL == sg_logfile) {
assert(false);
return false;
}
long before_len = ftell(sg_logfile);
if (before_len < 0) return false;
if(before_len+_len > sg_max_size){
if(!__roate()){
return false;
}
}
if (1 != fwrite(_data, _len, 1, sg_logfile)) {
int err = ferror(sg_logfile);
__writetips2console("write file error:%d", err);
ftruncate(fileno(sg_logfile), before_len);
fseek(sg_logfile, 0, SEEK_END);
char err_log[256] = {0};
snprintf(err_log, sizeof(err_log), "\nwrite file error:%d\n", err);
char tmp[256] = {0};
size_t len = sizeof(tmp);
LogBuffer::Write(err_log, strnlen(err_log, sizeof(err_log)), tmp, len);
fwrite(tmp, len, 1, sg_logfile);
return false;
}
return true;
}
template <typename T>
std::string NumberToString ( T Number )
{
std::ostringstream ss;
ss << Number;
return ss.str();
}
static std::string __calc_filename(const std::string& _logdir, const char* _prefix, const std::string& _fileext,unsigned int index){
std::string logfilepath = _logdir;
logfilepath += "/";
logfilepath += _prefix;
if(index){
logfilepath += ".";
logfilepath += NumberToString(index);
}
logfilepath += ".";
logfilepath += _fileext;
return logfilepath;
}
static bool __roate(){
if(sg_logfilename.empty() || sg_logdir.empty() || sg_logfileprefix.empty()){
return false;
}
fclose(sg_logfile);
sg_logfile = NULL;
for(auto i = sg_max_files; i > 0; --i){
std::string src = __calc_filename(sg_logdir,sg_logfileprefix.c_str(),LOG_EXT,i-1);
std::string target = __calc_filename(sg_logdir,sg_logfileprefix.c_str(),LOG_EXT,i);
boost::filesystem::path src_path(src);
boost::filesystem::path target_path(target);
if(boost::filesystem::exists(target_path)){
boost::filesystem::remove(target_path);
}
if(boost::filesystem::exists(src_path)){
boost::filesystem::rename(src_path,target_path);
}
}
sg_logfile = fopen(sg_logfilename.c_str(), "wb");
if (NULL == sg_logfile) {
__writetips2console("open file error:%d %s, path:%s", errno, strerror(errno), sg_logfilename.c_str());
return false;
}
return true;
}
static bool __openlogfile(const std::string& _log_dir){
if (sg_logdir.empty()) return false;
if (NULL != sg_logfile) {
return true;
}
sg_current_dir = _log_dir;
sg_logfilename = __calc_filename(_log_dir, sg_logfileprefix.c_str(), LOG_EXT,0);
sg_logfile = fopen(sg_logfilename.c_str(), "ab");
if (NULL == sg_logfile) {
__writetips2console("open file error:%d %s, path:%s", errno, strerror(errno), sg_logfilename.c_str());
}
return NULL != sg_logfile;
}
static void __log2file(const void* _data, size_t _len) {
if (NULL == _data || 0 == _len || sg_logdir.empty()) {
return;
}
ScopedLock lock_file(sg_mutex_log_file);
if (__openlogfile(sg_logdir)) {
__writefile(_data, _len);
if (kAppednerAsync == sg_mode) {
__closelogfile();
}
return;
}