/* ************************************************************************** */
/* **************************** log functions ******************************* */
/* ************************************************************************** */

#include <stdio.h>
#include <fcntl.h>
#include "MPSServer_defs.h"
#include "MPSServer_vars.h"

#if defined(CREATE_LOG)

void get_log_time(char *str, int maxlen)
{
	struct tm *newtime;
	struct timeval current_time;

	get_time(&current_time);								/* Get time in seconds and microseconds */
	newtime = gmtime( &current_time.tv_sec );				/* Convert time (seconds) to struct */
	strftime (str, maxlen, "%Y-%m-%d %H:%M:%S", newtime);	/* Write date and time (seconds) to string (UTC)*/
	if ( maxlen >= 24 )
	{
		/* Write miliseconds to string */
		sprintf(&(str[19]), ".%03i", (int) (current_time.tv_usec / 1000));
	}
}

void write_log_initialization()
{
	int file;

	if ( pthread_mutex_init(&log_mutex, NULL) )
	{
		fprintf(stderr, "Error: unable to initialize logfile mutex\n");
		log_file = NULL;
		return;
	}

	file = open(log_name, O_RDONLY);

	if ( file == -1 )
	{
		log_file = fopen(log_name, "w");
		if ( log_file == NULL )
		{
			printf("Unable to open logfile for writing...\n");
		}
		else
		{
			fprintf(log_file, "eventid;resultid;time;pid;sync/async;h6;h7;h8;h9;h10;h11;h12;errorid;text\n");
			fflush(log_file);
		}
	}
	else
	{
		close(file);

		log_file = fopen(log_name, "a");

		if ( log_file == NULL )
		{
			printf("Unable to open log file for writing...\n");
		}
		else
		{
			fprintf(log_file, "\n");
		}
	}
}

void write_log_deinitialization()
{
	if ( log_file != NULL )
	{
		fclose(log_file);
		log_file = NULL;

		pthread_mutex_destroy(&log_mutex);
	}
}

void write_log_server_startup(int resultid, char *reason)
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	if ( reason == NULL )
	{
		fprintf(log_file, "%i;%i;%s;;;0.0.0.0;%i;%i;;;;;;server startup\n", LEID_SERVER_STARTUP, resultid, cas, (int) listening_port, 100);
	}
	else
	{
		fprintf(log_file, "%i;%i;%s;;;0.0.0.0;%i;%i;;;;;;server startup - %s\n", LEID_SERVER_STARTUP, resultid, cas, (int) listening_port, 100, reason);
	}
	fflush(log_file);

	pthread_mutex_unlock(&log_mutex);
}

void write_log_server_shutdown()
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	fprintf(log_file, "%i;1;%s;;;;;;;;;;;server shutdown\n", LEID_SERVER_SHUTDOWN, cas);
	fflush(log_file);

	pthread_mutex_unlock(&log_mutex);
}

void write_log_client_connect(int resultid, long pid, char *reason)
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	if ( pid >= 0 )
	{
		fprintf(log_file, "%i;%i;%s;%li;;", LEID_CLIENT_CONNECT, resultid, cas, pid);
	}
	else
	{
		fprintf(log_file, "%i;%i;%s;;;", LEID_CLIENT_CONNECT, resultid, cas);
	}

	if ( reason == NULL )
	{
		fprintf(log_file, "%s;%li;;;;;;;client connect\n", inet_ntoa(((struct sockaddr_in *) &accepted_name)->sin_addr), (long) ntohs(((struct sockaddr_in *) &accepted_name)->sin_port));
	}
	else
	{
		fprintf(log_file, "%s;%li;;;;;;;client connect - %s\n", inet_ntoa(((struct sockaddr_in *) &accepted_name)->sin_addr), (long) ntohs(((struct sockaddr_in *) &accepted_name)->sin_port), reason);
	}
	fflush(log_file);

	pthread_mutex_unlock(&log_mutex);
}

void write_log_client_disconnect(long pid, char *reason)
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	if ( reason == NULL )
	{
		fprintf(log_file, "%i;1;%s;%li;;;;;;;;;;client disconnect\n", LEID_CLIENT_DISCONNECT, cas, pid);
	}
	else
	{
		fprintf(log_file, "%i;1;%s;%li;;;;;;;;;;client disconnect - %s\n", LEID_CLIENT_DISCONNECT, cas, pid, reason);
	}
	fflush(log_file);

	pthread_mutex_unlock(&log_mutex);
}

void write_log_operation_start(int resultid, long pid, int async, long newpid, long mid, long mlength, int errorid, char *reason)
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	if ( newpid >= 0 )
	{
		fprintf(log_file, "%i;%i;%s;%li;%s;%li;%li;%li;", LEID_OPERATION_START, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")), newpid, mid, mlength);
	}
	else
	{
		fprintf(log_file, "%i;%i;%s;%li;%s;;;;", LEID_OPERATION_START, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")));
	}

	if ( reason == NULL )
	{
		fprintf(log_file, ";;;;%i;operation start\n", errorid);
	}
	else
	{
		fprintf(log_file, ";;;;%i;operation start - %s\n", errorid, reason);
	}
	fflush(log_file);

	pthread_mutex_unlock(&log_mutex);
}

void write_log_operation_end(int resultid, long pid, int async, int errorid, char *reason)
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	fprintf(log_file, "%i;%i;%s;%li;%s;", LEID_OPERATION_END, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")));

	if ( reason == NULL )
	{
		fprintf(log_file, ";;;;;;;%i;operation end\n", errorid);
	}
	else
	{
		fprintf(log_file, ";;;;;;;%i;operation end - %s\n", errorid, reason);
	}
	fflush(log_file);

	pthread_mutex_unlock(&log_mutex);
}

void write_log_operation_create(int resultid, long pid, int async, u_long mlength, char *mtext, long mid, int errorid, char *reason)
{
	char cas[64];
	int maxlen, pos;

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	fprintf(log_file, "%i;%i;%s;%li;%s;%lu;", LEID_OPERATION_CREATE, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")), mlength);

	maxlen = MIN(16, mlength);

	for ( pos = 0; pos < maxlen; pos++ )
	{
		if ( pos != 0 ) fprintf(log_file, ",");
		fprintf(log_file, "0x%02x", (unsigned char) mtext[pos]);
	}

	if ( mid >= 0 )
	{
		fprintf(log_file, ";%li;", mid);
	}
	else
	{
		fprintf(log_file, ";;");
	}

	if ( reason == NULL )
	{
		fprintf(log_file, ";;;;%i;operation create\n", errorid);
	}
	else
	{
		fprintf(log_file, ";;;;%i;operation create - %s\n", errorid, reason);
	}
#if defined(CREATE_LOG)
	fflush(log_file);
#endif

	pthread_mutex_unlock(&log_mutex);
}

void write_log_operation_destroy(int resultid, long pid, int async, long mid, int errorid, char *reason)
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	fprintf(log_file, "%i;%i;%s;%li;%s;%li;", LEID_OPERATION_DESTROY, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")), mid);

	if ( reason == NULL )
	{
		fprintf(log_file, ";;;;;;%i;operation destroy\n", errorid);
	}
	else
	{
		fprintf(log_file, ";;;;;;%i;operation destroy - %s\n", errorid, reason);
	}
#if defined(CREATE_LOG)
	fflush(log_file);
#endif

	pthread_mutex_unlock(&log_mutex);
}


void write_log_operation_send(int resultid, long pid, int async, long mid, u_long num_recv_pids, u_long *recv_pids, long recv_pid, long new_mid, int errorid, char *reason)
{
	char cas[64];
	u_long pos;

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	if ( mid >= 0)
	{
		fprintf(log_file, "%i;%i;%s;%li;%s;%li;", LEID_OPERATION_SEND, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")), mid);
	}
	else
	{
		fprintf(log_file, "%i;%i;%s;%li;%s;;", LEID_OPERATION_SEND, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")));
	}

	fprintf(log_file, "%lu;", num_recv_pids);

	for ( pos = 0; pos < num_recv_pids; pos++ )
	{
		if ( pos != 0 ) fprintf(log_file, ",");
		fprintf(log_file, "%lu", recv_pids[pos]);
	}

	if ( recv_pid >= 0 )
	{
		fprintf(log_file, ";%li;", recv_pid);
	}
	else
	{
		fprintf(log_file, ";;");
	}

	if ( new_mid >= 0 )
	{
		fprintf(log_file, "%li;", new_mid);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( reason == NULL )
	{
		fprintf(log_file, ";;%i;operation send\n", errorid);
	}
	else
	{
		fprintf(log_file, ";;%i;operation send - %s\n", errorid, reason);
	}
#if defined(CREATE_LOG)
	fflush(log_file);
#endif

	pthread_mutex_unlock(&log_mutex);
}

void write_log_operation_recv(int resultid, long pid, int async, u_long num_send_pids, u_long *send_pids, char *fname, long send_pid, long mid, long old_mid, int mlength, int errorid, char *reason)
{
	char cas[64];
	u_long pos;

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	fprintf(log_file, "%i;%i;%s;%li;%s;%lu;", LEID_OPERATION_RECV, resultid, cas, pid, (async == 0)?(""):((async == 1)?("async"):("sync")), num_send_pids);

	for ( pos = 0; pos < num_send_pids; pos++ )
	{
		if ( pos != 0 ) fprintf(log_file, ",");
		fprintf(log_file, "%lu", send_pids[pos]);
	}

	if ( fname != NULL )
	{
		fprintf(log_file, ";%s;", fname);
	}
	else
	{
		fprintf(log_file, ";;");
	}

	if ( send_pid >= 0 )
	{
		fprintf(log_file, "%li;", send_pid);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( mid >= 0 )
	{
		fprintf(log_file, "%li;", mid);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( old_mid >= 0 )
	{
		fprintf(log_file, "%li;", old_mid);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( mlength > 0 )
	{
		fprintf(log_file, "%i;", mlength);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( reason == NULL )
	{
		fprintf(log_file, "%i;operation recv\n", errorid);
	}
	else
	{
		fprintf(log_file, "%i;operation recv - %s\n", errorid, reason);
	}
#if defined(CREATE_LOG)
	fflush(log_file);
#endif

	pthread_mutex_unlock(&log_mutex);
}

void write_log_sendrecv_exec(int resultid, long recv_pid, long send_pid, long recv_mid, long send_mid, int mlength, int errorid, char *reason)
{
	char cas[64];

	pthread_mutex_lock(&log_mutex);

	get_log_time(cas, 63);

	if ( recv_pid >= 0)
	{
		fprintf(log_file, "%i;%i;%s;%li;;", LEID_SENDRECV_EXEC, resultid, cas, recv_pid);
	}
	else
	{
		fprintf(log_file, "%i;%i;%s;;;", LEID_SENDRECV_EXEC, resultid, cas);
	}

	if ( send_pid >= 0 )
	{
		fprintf(log_file, "%li;", send_pid);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( recv_mid >= 0 )
	{
		fprintf(log_file, "%li;", recv_mid);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( send_mid >= 0 )
	{
		fprintf(log_file, "%li;", send_mid);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( mlength > 0 )
	{
		fprintf(log_file, "%i;", mlength);
	}
	else
	{
		fprintf(log_file, ";");
	}

	if ( reason == NULL )
	{
		fprintf(log_file, ";;;%i;execute send/recv\n", errorid);
	}
	else
	{
		fprintf(log_file, ";;;%i;execute send/recv - %s\n", errorid, reason);
	}
#if defined(CREATE_LOG)
	fflush(log_file);
#endif

	pthread_mutex_unlock(&log_mutex);
}

#endif
