#include <sys/stat.h>
#include <sys/types.h>

static pthread_mutex_t  lock_record_logpath = PTHREAD_MUTEX_INITIALIZER;
#define LOGPATH_LOCK pthread_mutex_lock(&lock_record_logpath)
#define LOGPATH_UNLOCK pthread_mutex_unlock(&lock_record_logpath)


static pthread_mutex_t  lock_record_log = PTHREAD_MUTEX_INITIALIZER;
#define LOG_LOCK pthread_mutex_lock(&lock_record_log)
#define LOG_UNLOCK pthread_mutex_unlock(&lock_record_log)

#define MAX_LOG_COUNT 5000
static char **log_prepare = NULL;
static char **log_writing = NULL;
static int log_thread_exit = 1;
static int log_idx = 0;

void create_dir(char *create_path)
{
	char tmp_path[256];

	strcpy(tmp_path,create_path);

	int  i,len   =   strlen(tmp_path);

	for(i=1;   i<len;   i++)
	{
		if(tmp_path[i]=='/')
		{
			tmp_path[i]   =   0;
			if(   access(tmp_path,   F_OK)!=0   )
			{
				if(mkdir(tmp_path,   0755)==-1)
				{
					perror("mkdir   error");
				}
			}
			tmp_path[i]   =   '/';
		}
	}

}

static void *record_log_thread( void *arg )
{
	char *log_str;
	FILE *log_fp = NULL;
	char **tmp = NULL;
	char tmp_path[256];
	int i = 0;
	LOGPATH_LOCK;
	strcpy(tmp_path,log_path);
	LOGPATH_UNLOCK;

//	create_dir( log_path );
	create_dir( tmp_path );

	log_thread_exit = 0;

//	log_fp = fopen(log_path, "a");

	while( !log_thread_exit ) {
		LOGPATH_LOCK;
		strcpy(tmp_path,log_path);
		LOGPATH_UNLOCK;
		if( !log_fp ) {
//			LOGPATH_LOCK;
//			log_fp = fopen(log_path, "a");
			log_fp = fopen(tmp_path, "a");
//			LOGPATH_UNLOCK;
		}

		//prepare log strings
		LOG_LOCK;
		tmp = log_writing;
		log_writing = log_prepare;
	//	log_prepare = log_writing;
		log_prepare = tmp;
		log_idx=0;
		LOG_UNLOCK;

		i = 0;
		while( i < MAX_LOG_COUNT ) {
			log_str = log_writing[i];

			if( log_str == NULL ) {
				break;
			}

			if( log_fp ) {
//				fwrite( log_str, 1, strlen(log_str), log_fp );  //write to file
				fwrite( log_str, strlen(log_str), 1,  log_fp );
			}

			free( log_str );        //free
			log_writing[i] = NULL;  //clear

			//next
			i++;
		}
		if(log_fp) {
			fclose(log_fp);
			log_fp = NULL;
		}
		usleep(799999);
	} //while

	if( log_fp ) {
		fclose(log_fp);
	}
	if( log_prepare ) free( log_prepare );
	if( log_writing ) free( log_writing );
	log_prepare = NULL;
	log_writing = NULL;

	//free self thread resources
	pthread_detach(pthread_self());

	return NULL;	
}

/* write error in logfile */
void record_log(char *str)
{
	static int log_thread_started = 0;
	time_t tamp;
	char str_tm[4];
	char log_str[512];
	struct tm tmptr;
	struct timeval tv;
	struct timezone tz;
	pthread_t pid;
//	int ret = 0;
	char *keepstr = NULL;

	tamp = time(NULL);
	memset(str_tm, 0, sizeof(str_tm));
	memset(log_str, 0, sizeof(log_str));
	localtime_r(&tamp, &tmptr);
	gettimeofday(&tv, &tz);
	snprintf(str_tm, sizeof(str_tm), "%d", (int)tv.tv_usec/1000);
	if(str_tm[1] == '\0')str_tm[1] = '0';
	if(str_tm[2] == '\0')str_tm[2] = '0';
//	ret = strftime(log_str, sizeof(log_str), "%F %T. ", &tmptr );
//	snprintf(log_str+ret, sizeof(log_str)-ret, " %s %s %s", str_tm, process_name, str );
//
		strftime(log_str, sizeof(log_str), "%F %T.", &tmptr);
		strcat(log_str, str_tm);
		strcat(log_str, " ");
		strcat(log_str, process_name);
		strcat(log_str, " ");
		strcat(log_str, str);

	//check log thread
	if( log_thread_started == 0 ) {
		log_thread_started = 1;
		log_prepare = (char **)malloc( sizeof(char *)*MAX_LOG_COUNT );
		log_writing = (char **)malloc( sizeof(char *)*MAX_LOG_COUNT );
		memset( log_prepare, 0, sizeof(char *) *MAX_LOG_COUNT );
		memset( log_writing, 0, sizeof(char *) *MAX_LOG_COUNT );
		log_idx = 0;

		pthread_create( &pid, NULL, record_log_thread, (void *)NULL );
	}

	LOG_LOCK;
	if(log_idx < MAX_LOG_COUNT){
		keepstr = strdup( log_str );
		if(!keepstr){
			LOG_UNLOCK;
			return;
		}
	//LOG_LOCK;
		if( log_prepare ) {
			log_prepare[log_idx] = keepstr;
			log_idx++;
		}
	}
	LOG_UNLOCK;	
}

