<commit_before>//
//  mit_log_module.c
//
//  Created by gtliu on 7/3/13.
//  Copyright (c) 2013 GT. All rights reserved.
//

#define MIT_derrprintf(fmt, args...) printf("%s %d ERROR:%s: "fmt"\n", __func__, __LINE__, strerror(errno), ##args)

/** logmodule debug switch macro */
/**
 * If define the marco message of log module will be printed into stdout.
 * It can be used when you want to debug the log module.
 *
 * Without the definition you will see nothing.
 * It can be used when you want to relase the log module.
 */
//#define MIT_DEBUG

#ifdef  MIT_DEBUG
#define MIT_dputs(str) printf("%s %d: %s\n", __func__, __LINE__, str)
#define MIT_dprintf(fmt, args...) printf("%s %d: "fmt"\n", __func__, __LINE__, ##args)
#define MITLogEnter  printf("%s:%d %s\n", __func__, __LINE__, "Enter -->");
#define MITLogExit   printf("%s:%d %s\n", __func__, __LINE__, "<--Exist");
#else
#define MIT_dputs(str)
#define MIT_dprintf(fmt, args...)
#define MITLogEnter
#define MITLogExit
#endif

#include "../include/mit_log_module.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <dirent.h>
#include <fnmatch.h>
#include <time.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>

static int mit_log_opened_flag;

#if MITLOG_DEBUG_ENABLE
static char const *MITLogLevelHeads[]  = {"[COMMON]", "[WARNING]", "[ERROR]"};

#else
static char const *MITLogFileSuffix[]  = {".comm", ".warn", ".err"};
static int MITLogFileMaxNum[] = {MITLOG_MAX_COMM_FILE_NUM, MITLOG_MAX_WARN_FILE_NUM,\
				 MITLOG_MAX_ERROR_FILE_NUM};

static long long MITLogBufferMaxSize[] = {MITLOG_MAX_COMM_BUFFER_SIZE,\
				 MITLOG_MAX_WARN_BUFFER_SIZE, MITLOG_MAX_ERROR_BUFFER_SIZE};

static char applicationName[MITLOG_MAX_APP_NAME_LEN];
static char appLogFilePath[MITLOG_MAX_FILE_NAME_PATH_LEN];
static char *logFilePaths[MITLOG_FILE_INDEX_NUM];
static char *logFileBuffer[MITLOG_FILE_INDEX_NUM];

static pthread_rwlock_t bufferRWlock;     // use for the logFileBuffer

#endif
static FILE *originFilePointers[MITLOG_FILE_INDEX_NUM];


/*************************** Inner Tools Function ********************************/
#ifndef MITLOG_DEBUG_ENABLE
// return the log file path, exp: /data/logs/TestApp.comm
static inline void MITGetLogFilePathPrefix(MITLogFileIndex aryIndex, char *chrAry)
{
    const char *fileSuffix = MITLogFileSuffix[aryIndex];
    sprintf(chrAry, "%s%s%s", appLogFilePath, applicationName, fileSuffix);
}

// get origin file size and next should be updated log file's name
MITFuncRetValue MITGetLogInfoByIndex(MITLogFileIndex aryIndex, char *nextStoreFile, long long *fileSize)
{
    const char *fileSuffix = MITLogFileSuffix[aryIndex];
    
    // pattern:  TestApp.comm.*
    char logNumPattern[MITLOG_MAX_LOG_FILE_LEN] = {0};
    sprintf(logNumPattern, "%s%s%s", applicationName, fileSuffix, ".*");
    // origin log file name
    char originFileName[MITLOG_MAX_LOG_FILE_LEN] = {0};
    sprintf(originFileName, "%s%s", applicationName, fileSuffix);
    
    DIR *dirfd = NULL;
    struct dirent *entry = NULL;
    
    if ((dirfd = opendir(appLogFilePath)) == NULL) {
        MIT_derrprintf("opendir() faild");
        return MIT_RETV_FAIL;
    }
    // 1 mean the '.' between num and suffix. TestApp.comm.1
    long long partLen = strlen(applicationName) + strlen(fileSuffix) + 1;
    int currentMaxFileNum = 0;
    time_t minModifyTime = 0;
    while ((entry = readdir(dirfd)) != NULL) {
        char *dname = entry->d_name;
        if (strcmp(dname, ".") == 0 ||
            strcmp(dname, "..") == 0) {
            continue;
        }
        // get origin log file size
        if (0 == strcmp(dname, originFileName)) {
            char logfilepath[MITLOG_MAX_FILE_NAME_PATH_LEN] = {0};
            sprintf(logfilepath, "%s%s", appLogFilePath, originFileName);
            MIT_dputs(logfilepath);
            struct stat tstat;
            if (stat(logfilepath, &tstat) < 0) {
                MIT_derrprintf("stat() %s faild", logfilepath);
                return MIT_RETV_FAIL;
            } else {
                *fileSize = tstat.st_size;
            }
        } else if (fnmatch(logNumPattern, dname, FNM_PATHNAME|FNM_PERIOD) == 0) {
            // get next store file
            int tt = atoi(&dname[partLen]);
            if (tt > currentMaxFileNum) {
                currentMaxFileNum = tt;
            }
            char logfilepath[MITLOG_MAX_FILE_NAME_PATH_LEN] = {0};
            sprintf(logfilepath, "%s%s", appLogFilePath, dname);
            MIT_dputs(logfilepath);
            struct stat tstat;
            if (stat(logfilepath, &tstat) < 0) {
                MIT_derrprintf("stat() %s faild", logfilepath);
                return MIT_RETV_FAIL;
            }
            if (minModifyTime == 0 || tstat.st_mtime < minModifyTime) {
                minModifyTime = tstat.st_mtime;
                memset(nextStoreFile, 0, MITLOG_MAX_FILE_NAME_PATH_LEN);
                strncpy(nextStoreFile, logfilepath, MITLOG_MAX_FILE_NAME_PATH_LEN);
            }
        }
    }
    MIT_dprintf("currentMaxFileNum:%d  nextStoreFile:%s", currentMaxFileNum, nextStoreFile);
    if (currentMaxFileNum < MITLogFileMaxNum[aryIndex]) {
        ++currentMaxFileNum;
        memset(nextStoreFile, 0, MITLOG_MAX_FILE_NAME_PATH_LEN);
        sprintf(nextStoreFile, "%s%s%s.%d", appLogFilePath, applicationName,\
				 MITLogFileSuffix[aryIndex], currentMaxFileNum);
    }
    MIT_dprintf("currentMaxFileNum:%d  nextStoreFile:%s", currentMaxFileNum, nextStoreFile);
    closedir(dirfd);<commit_msg>fix Log Module add closedir()<commit_after>//
//  mit_log_module.c
//
//  Created by gtliu on 7/3/13.
//  Copyright (c) 2013 GT. All rights reserved.
//

#define MIT_derrprintf(fmt, args...) printf("%s %d ERROR:%s: "fmt"\n", __func__, __LINE__, strerror(errno), ##args)

/** logmodule debug switch macro */
/**
 * If define the marco message of log module will be printed into stdout.
 * It can be used when you want to debug the log module.
 *
 * Without the definition you will see nothing.
 * It can be used when you want to relase the log module.
 */
//#define MIT_DEBUG

#ifdef  MIT_DEBUG
#define MIT_dputs(str) printf("%s %d: %s\n", __func__, __LINE__, str)
#define MIT_dprintf(fmt, args...) printf("%s %d: "fmt"\n", __func__, __LINE__, ##args)
#define MITLogEnter  printf("%s:%d %s\n", __func__, __LINE__, "Enter -->");
#define MITLogExit   printf("%s:%d %s\n", __func__, __LINE__, "<--Exist");
#else
#define MIT_dputs(str)
#define MIT_dprintf(fmt, args...)
#define MITLogEnter
#define MITLogExit
#endif

#include "../include/mit_log_module.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <dirent.h>
#include <fnmatch.h>
#include <time.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>

static int mit_log_opened_flag;

#if MITLOG_DEBUG_ENABLE
static char const *MITLogLevelHeads[]  = {"[COMMON]", "[WARNING]", "[ERROR]"};

#else
static char const *MITLogFileSuffix[]  = {".comm", ".warn", ".err"};
static int MITLogFileMaxNum[] = {MITLOG_MAX_COMM_FILE_NUM, MITLOG_MAX_WARN_FILE_NUM,\
				 MITLOG_MAX_ERROR_FILE_NUM};

static long long MITLogBufferMaxSize[] = {MITLOG_MAX_COMM_BUFFER_SIZE,\
				 MITLOG_MAX_WARN_BUFFER_SIZE, MITLOG_MAX_ERROR_BUFFER_SIZE};

static char applicationName[MITLOG_MAX_APP_NAME_LEN];
static char appLogFilePath[MITLOG_MAX_FILE_NAME_PATH_LEN];
static char *logFilePaths[MITLOG_FILE_INDEX_NUM];
static char *logFileBuffer[MITLOG_FILE_INDEX_NUM];

static pthread_rwlock_t bufferRWlock;     // use for the logFileBuffer

#endif
static FILE *originFilePointers[MITLOG_FILE_INDEX_NUM];


/*************************** Inner Tools Function ********************************/
#ifndef MITLOG_DEBUG_ENABLE
// return the log file path, exp: /data/logs/TestApp.comm
static inline void MITGetLogFilePathPrefix(MITLogFileIndex aryIndex, char *chrAry)
{
    const char *fileSuffix = MITLogFileSuffix[aryIndex];
    sprintf(chrAry, "%s%s%s", appLogFilePath, applicationName, fileSuffix);
}

// get origin file size and next should be updated log file's name
MITFuncRetValue MITGetLogInfoByIndex(MITLogFileIndex aryIndex, char *nextStoreFile, long long *fileSize)
{
    const char *fileSuffix = MITLogFileSuffix[aryIndex];
    
    // pattern:  TestApp.comm.*
    char logNumPattern[MITLOG_MAX_LOG_FILE_LEN] = {0};
    sprintf(logNumPattern, "%s%s%s", applicationName, fileSuffix, ".*");
    // origin log file name
    char originFileName[MITLOG_MAX_LOG_FILE_LEN] = {0};
    sprintf(originFileName, "%s%s", applicationName, fileSuffix);
    
    DIR *dirfd = NULL;
    struct dirent *entry = NULL;
    
    if ((dirfd = opendir(appLogFilePath)) == NULL) {
        MIT_derrprintf("opendir() faild");
        return MIT_RETV_FAIL;
    }
    // 1 mean the '.' between num and suffix. TestApp.comm.1
    long long partLen = strlen(applicationName) + strlen(fileSuffix) + 1;
    int currentMaxFileNum = 0;
    time_t minModifyTime = 0;
    while ((entry = readdir(dirfd)) != NULL) {
        char *dname = entry->d_name;
        if (strcmp(dname, ".") == 0 ||
            strcmp(dname, "..") == 0) {
            continue;
        }
        // get origin log file size
        if (0 == strcmp(dname, originFileName)) {
            char logfilepath[MITLOG_MAX_FILE_NAME_PATH_LEN] = {0};
            sprintf(logfilepath, "%s%s", appLogFilePath, originFileName);
            MIT_dputs(logfilepath);
            struct stat tstat;
            if (stat(logfilepath, &tstat) < 0) {
                MIT_derrprintf("stat() %s faild", logfilepath);
                closedir(dirfd);
                return MIT_RETV_FAIL;
            } else {
                *fileSize = tstat.st_size;
            }
        } else if (fnmatch(logNumPattern, dname, FNM_PATHNAME|FNM_PERIOD) == 0) {
            // get next store file
            int tt = atoi(&dname[partLen]);
            if (tt > currentMaxFileNum) {
                currentMaxFileNum = tt;
            }
            char logfilepath[MITLOG_MAX_FILE_NAME_PATH_LEN] = {0};
            sprintf(logfilepath, "%s%s", appLogFilePath, dname);
            MIT_dputs(logfilepath);
            struct stat tstat;
            if (stat(logfilepath, &tstat) < 0) {
                MIT_derrprintf("stat() %s faild", logfilepath);
                closedir(dirfd);
                return MIT_RETV_FAIL;
            }
            if (minModifyTime == 0 || tstat.st_mtime < minModifyTime) {
                minModifyTime = tstat.st_mtime;
                memset(nextStoreFile, 0, MITLOG_MAX_FILE_NAME_PATH_LEN);
                strncpy(nextStoreFile, logfilepath, MITLOG_MAX_FILE_NAME_PATH_LEN);
            }
        }
    }
    MIT_dprintf("currentMaxFileNum:%d  nextStoreFile:%s", currentMaxFileNum, nextStoreFile);
    if (currentMaxFileNum < MITLogFileMaxNum[aryIndex]) {
        ++currentMaxFileNum;
        memset(nextStoreFile, 0, MITLOG_MAX_FILE_NAME_PATH_LEN);
        sprintf(nextStoreFile, "%s%s%s.%d", appLogFilePath, applicationName,\
				 MITLogFileSuffix[aryIndex], currentMaxFileNum);
    }
    MIT_dprintf("currentMaxFileNum:%d  nextStoreFile:%s", currentMaxFileNum, nextStoreFile);

    closedir(dirfd);
{'fraction_non_alphanumeric': 0.1332264671831864, 'fraction_numerical': 0.004630866506367442, 'mean_word_length': 3.315910837817064, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '194762', 'n_tokens_mistral': 3800, 'n_tokens_neox': 3694, 'n_words': 861}