static void _log_write_in_level(t_log* logger, t_log_level level, const char* message_template, va_list list_arguments) {

	if (_isEnableLevelInLogger(logger, level)) {
		char *message, *time, *buffer;
		unsigned int thread_id;

                message = string_from_vformat(message_template, list_arguments);
		time = temporal_get_string_time();
		thread_id = process_get_thread_id();

		buffer = string_from_format("[%s] %s %s/(%d:%d): %s\n",
                                log_level_as_string(level),
                                time,
                                logger->program_name,
				logger->pid,
                                thread_id,
                                message);

		if (logger->file != NULL) {
			txt_write_in_file(logger->file, buffer);
		}

		if (logger->is_active_console) {
			txt_write_in_stdout(buffer);
		}

		free(time);
		free(message);
		free(buffer);
	}
}
int escuchar(int puertoEscucha, int socketServer, int (*funcionParaProcesarMensaje)(int, header_t*, void*, t_log*), void* extra,  t_log* logger) {

	int miPID = process_get_thread_id();
	log_info(logger, "************** Comenzamos el proceso de escucha (PID: %d) ***************", miPID);

	//Logica principal para administrar conexiones
	fd_set masterFDList; //file descriptor list
	fd_set readFDList; //file descriptor list temporal para el select()
	int maxFDNumber; //maximo numero de file descriptor para hacer las busquedas en comunicaciones

	int socketEscucha;//socket escucha
	int nuevoFD;//file descriptor del cliente aceptado
	struct sockaddr_storage remoteaddr; //dirección del cliente
	socklen_t addrlen;

	char remoteIP[INET6_ADDRSTRLEN];

	int socketActual;

	struct addrinfo hints;

	FD_ZERO(&masterFDList);	//limpiamos la lista principal
	FD_ZERO(&readFDList); //limpiamos la lista de lectura

	 //Lleno la estructura de tipo addrinfo
	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;

	t_socket_info socketInfo;
	socketInfo.sin_addr.s_addr = INADDR_ANY;
	socketInfo.sin_family = AF_INET;
	socketInfo.sin_port = htons(puertoEscucha);
	memset(&(socketInfo.sin_zero), '\0', 8);

	socketEscucha = crearSocket();

	bindearSocketYLoguear(socketEscucha, socketInfo, logger);

	// el socket se pone en modo server
	if (listen(socketEscucha, 10) == -1) {
		log_info(logger, "listen: %s", strerror(errno));
		exit(3);
	}

	// agregamos el socket a la lista principal
	FD_SET(socketEscucha, &masterFDList);


	// guardamos el maximo numero de descriptor
	maxFDNumber = socketEscucha;
	if (socketServer > -1) {
		FD_SET(socketServer, &masterFDList);
		if (socketServer > maxFDNumber) {    // grabamos el mayor FD
			maxFDNumber = socketServer;
		}
	}

//	log_info(logger, "socketEscucha %d", socketEscucha);
//	log_info(logger, "socketServer %d", socketServer);
//	log_info(logger, "maxFDNumber %d", maxFDNumber);

	for(;;){

		readFDList = masterFDList; // copy it

		if (select(maxFDNumber+1, &readFDList, NULL, NULL, NULL) == -1) {
			log_info(logger, "select: %s", strerror(errno));
			exit(4);
		}

		// recorremos las conexiones viendo si hay datos para leer
		for(socketActual = 0; socketActual <= maxFDNumber; socketActual++) {
//			log_debug(logger, "Reviso socket %d", socketActual);
			if (FD_ISSET(socketActual, &readFDList)) { // checkeamos si hay datos

				if (socketActual == socketEscucha) {

					// manejamos conexiones nuevas
					addrlen = sizeof remoteaddr;
					nuevoFD = accept(socketEscucha, (struct sockaddr *) &remoteaddr, &addrlen);

					if (nuevoFD == -1) {
						log_error(logger, string_from_format( "Hubo un error en el accept para el fd: %i", socketActual));
					} else {
						FD_SET(nuevoFD, &masterFDList); // agregamos a la lista principal
						if (nuevoFD > maxFDNumber) {    // grabamos el mayor FD
							maxFDNumber = nuevoFD;
						}
						void* inAddr = get_in_addr((struct sockaddr*) &remoteaddr);

						log_info(logger, string_from_format("Se recibe una nueva conexion desde %s en el socket %d\n",
								inet_ntop(remoteaddr.ss_family, inAddr, remoteIP, INET6_ADDRSTRLEN), nuevoFD));
					}

				} else {

					header_t mensaje;
					int respRecibir = recibir_header_simple(socketActual, &mensaje);
					header_t* pMensaje = &mensaje;

					//if (pMensaje->tipo == ERR_CONEXION_CERRADA) {
					if (respRecibir == ERROR) {
						//Removes from master set and say good bye! :)
						close(socketActual); // bye!

						FD_CLR(socketActual, &masterFDList); // remove from master set
						log_info(logger, "El socket %d cerró la conexion.", socketActual);

					} else {
						log_debug(logger, "Recibi un header tipo: %d, tamanio: %d", pMensaje->tipo, pMensaje->largo_mensaje);
						FD_CLR(socketActual, &masterFDList); // remove from master set
						int result = funcionParaProcesarMensaje(socketActual, &mensaje, extra, logger);

						if(result == ERROR) {
							//Removes from master set and say good bye! :)
							close(socketActual); // bye!

							log_info(logger, "El socket %d cerró la conexion.", socketActual);
						} else {
							FD_SET(socketActual, &masterFDList); // agregamos a la lista principal
						}
						//FD_CLR(socketActual, &readFDList); //HACK faltaba limpiar, sino me traia los mensajes infinitamente
					}


				}
				//FD_CLR(socketActual, &readFDList); //HACK faltaba limpiar, sino me traia los mensajes infinitamente
			}
		}
	}
	return 0;
}
Exemple #3
0
void * procesarInstruccion() {

	t_log *logCpu;
	protocolo_planificador_cpu* datosParaProcesar = malloc(sizeof(protocolo_planificador_cpu));
	protocolo_cpu_memoria* mensajeAMemoria = malloc( sizeof(protocolo_cpu_memoria));
	protocolo_memoria_cpu* mensajeDeMemoria = malloc(sizeof(protocolo_memoria_cpu));
	int tid = process_get_thread_id();
	int socketPlanifAux;
	int maximoInstruccion = (int)(60.0f/config->retardo);
	t_list * listaTiempos = list_create();

	// creacion de la instancia de log
	char* nombrelog = string_new();
	string_append_with_format(&nombrelog,"../src/logCPU%d",tid);
	string_append(&nombrelog,".txt");
	logCpu = log_create(nombrelog, "cpu.c", false, LOG_LEVEL_INFO);
	free(nombrelog);

	/*solo para que quede lindo cuando imprime*/
	pthread_mutex_lock(&mutexConectarPlanificador);
	printf("Conectando CPU %d al Planificador (%s : %s)... ", tid, config->ipPlanificador,config->puertoPlanificador);
	client_init(&socketPlanifAux, config->ipPlanificador, config->puertoPlanificador);
	printf("OK\n");
	pthread_mutex_unlock(&mutexConectarPlanificador);

	if (socketPlanifAux == -1)
		log_info(logCpu, "Fallo al conectar con Planificador");
	else
		log_info(logCpu, "Conectado al Planificador");

	if (socketMemoria == -1)
		log_info(logCpu, "CPU %d fallo al conectar con Memoria", tid);
	else
		log_info(logCpu, "CPU %d se conecto con Memoria", tid);

	int status;
	while (1) {

		status = deserializarPlanificador(datosParaProcesar, socketPlanifAux);
		if(status <= 0) pthread_exit(0);
		if(datosParaProcesar->tipoOperacion == 'u'){

			/*tiempo actual*/
			time_t tiempoActual = time(NULL);

			int i;
			int cantidadInstruccionesLeidas = 0;

			for(i = 0; i < list_size(listaTiempos); i++){
				time_t * tiempoInstruccion = list_get(listaTiempos,i);

				if (tiempoActual - (*tiempoInstruccion) <= 60)
					cantidadInstruccionesLeidas++;
			}

			/*borro los tiempos de las isntrucciones que son anteriores al minuto*/
			for(i = list_size(listaTiempos) - 1; i >= 0; i--){
				time_t * tiempoInstruccion = list_get(listaTiempos,i);

				if (tiempoActual - (*tiempoInstruccion) > 60){
					free(list_remove(listaTiempos,i));
				}
			}

			datosParaProcesar->pid = tid;
			datosParaProcesar->counterProgram = ((int)(((float)cantidadInstruccionesLeidas/(float)maximoInstruccion) * 100.0f));
			enviarAPlanificador(datosParaProcesar,socketPlanifAux);
		}
		else{
			logueoRecepcionDePlanif(datosParaProcesar,tid,logCpu);

			FILE* archivo = fopen(datosParaProcesar->mensaje, "r+");

			if (archivo == NULL){
				printf("Error al abrir mCod: %s\n", datosParaProcesar->mensaje);
				break;
			}

			fseek(archivo, 0, SEEK_END);
			int tamanio = ftell(archivo);
			fseek(archivo, 0, SEEK_SET);
			char* lineaLeida = malloc(tamanio);
			int quantum = 0;

			while ((!feof(archivo) && (quantum < datosParaProcesar->quantum || datosParaProcesar->quantum == 0))) {

				//calcularTamanioDeLinea(archivo,&tamanio);
				char* instruccionLeida = leerInstruccion(&(datosParaProcesar->counterProgram), lineaLeida, archivo,tamanio);
				char** linea = string_split(instruccionLeida, ";");
				printf("pid-> %d ejecutar %s\n", datosParaProcesar->pid, *linea);
				free(*linea);

				/*si no "entiende" la instruccion pasa a la siguiente*/
				if (!interpretarInstruccion(instruccionLeida, datosParaProcesar, mensajeAMemoria, socketPlanifAux,logCpu))
					continue;

				if (datosParaProcesar->tipoOperacion == 'e') break;

				/*asi la comunicacion con la memoria es atomica*/
				pthread_mutex_lock(&mutex);
				enviarAMemoria(mensajeAMemoria);
				deserializarMemoria(mensajeDeMemoria, socketMemoria);
				pthread_mutex_unlock(&mutex);
				loguearEstadoMemoria(mensajeDeMemoria,instruccionLeida,logCpu);

				switch (mensajeDeMemoria->codOperacion){

					case 'f': {
						actualizarOperacionPaquetePlanificador(datosParaProcesar, 'f');
						enviarAPlanificador(datosParaProcesar,socketPlanifAux);

						/*me voy al eof para salir del while*/
						while(getc(archivo) != EOF);
						continue;
					}
					break;

					case 'i':{
						/*para saber desde el planifciador si el fallo es por inicializacion*/
						datosParaProcesar->tipoProceso = 'i';
						actualizarOperacionPaquetePlanificador(datosParaProcesar, mensajeDeMemoria->codAux);
						enviarAPlanificador(datosParaProcesar,socketPlanifAux);

						if (mensajeDeMemoria->codAux == 'a'){

							/*me voy al eof para salir del while*/
							while(getc(archivo) != EOF);
							continue;
						}
					}
					break;

					case 'l':
					case 'e':{
						if (mensajeDeMemoria->codAux == 'a'){
							/*para saber desde el planifciador si el fallo es por lectura o escritura*/
							datosParaProcesar->tipoProceso = mensajeDeMemoria->codOperacion;
							actualizarOperacionPaquetePlanificador(datosParaProcesar, 'a');
							enviarAPlanificador(datosParaProcesar,socketPlanifAux);
							datosParaProcesar->tipoOperacion = 'f';

							/*me voy al eof para salir del while*/
							while(getc(archivo) != EOF);
							continue;
						}
					}
					break;
				}
				sleep(config->retardo);

				/*guardo tiempo en el que se ejecuto la instruccion*/
				time_t * tiempoInstruccion = malloc(sizeof(time_t));
				*tiempoInstruccion = time(NULL);
				list_add(listaTiempos, tiempoInstruccion);

				/*incremento quatum solo para operaciones leer y escribir*/
				if (mensajeDeMemoria->codOperacion != 'i' && mensajeDeMemoria->codOperacion != 'f')
					quantum++;

			}

			/*es rr y salio por quantum y no por io*/
			if (datosParaProcesar->quantum != 0) {
				if (datosParaProcesar->quantum == quantum){
					if (datosParaProcesar->tipoOperacion != 'e' && datosParaProcesar->tipoOperacion != 'f'){
						actualizarOperacionPaquetePlanificador(datosParaProcesar, 'q');
						enviarAPlanificador(datosParaProcesar, socketPlanifAux);
						printf("pid-> %d salio por quantum\n", datosParaProcesar->pid);
					}
				}
			}
			free(lineaLeida);
			fclose(archivo);
		}
	}
	free(mensajeAMemoria);
	free(mensajeDeMemoria);
	free(datosParaProcesar);
	close(socketPlanifAux);
	log_info(logCpu, "Cerrada conexion saliente");
	log_destroy(logCpu);
	return 0;
}
void escucha(int puerto) {

	int myPID = process_get_thread_id();
	log_info(LOGGER, "************** Comienza a escuchar MaRTA a los Jobs (PID: %d) ***************",myPID);

	//Logica principal para administrar conexiones
	fd_set master; //file descriptor list
	fd_set read_fds; //file descriptor list temporal para el select()
	int fdmax; //maximo numero de file descriptor para hacer las busquedas en comunicaciones

	int listener;//socket escucha
	int newfd;//file descriptor del cliente aceptado
	struct sockaddr_storage remoteaddr; //dirección del cliente
	socklen_t addrlen;

	char remoteIP[INET6_ADDRSTRLEN];

	int i; // socket entrante

	struct addrinfo hints;

	FD_ZERO(&master);	//clear the master
	FD_ZERO(&read_fds); //clear the temp set

	 //Lleno la estructura de tipo addrinfo
	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;

	t_socket_info socketInfo;
	socketInfo.sin_addr.s_addr = INADDR_ANY;
	socketInfo.sin_family = AF_INET;
	socketInfo.sin_port = htons(puerto);
	memset(&(socketInfo.sin_zero), '\0', 8);

	listener = crearSocket();

	bindearSocket(listener, socketInfo);

	// listen turns on server mode for a socket.
	if (listen(listener, 10) == -1) {
		perror("listen");
		exit(3);
	}

	// add the listener to the master set
	FD_SET(listener, &master);

	// keep track of the biggest file descriptor
	fdmax = listener; // so far, it's this one

	for(;;){

		read_fds = master; // copy it

		if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
			perror("select");
			exit(4);
		}

		// run through the existing connections looking for data to read
		for(i = 0; i <= fdmax; i++) {

			if (FD_ISSET(i, &read_fds)) { // we got one!!

				if (i == listener) {

					// handle new connections
					addrlen = sizeof remoteaddr;
					newfd = accept(listener, (struct sockaddr *) &remoteaddr,
							&addrlen);

					if (newfd == -1) {
						log_error(LOGGER, string_from_format( "Hubo un error en el accept para el fd: %i", i));
					} else {
						FD_SET(newfd, &master); // add to master set
						if (newfd > fdmax) {    // keep track of the max
							fdmax = newfd;
						}

						//Shows the new connection administrated
						log_info(LOGGER,
								string_from_format(
										"selectserver: new connection from %s on socket %d\n",
										inet_ntop(remoteaddr.ss_family,
												get_in_addr( (struct sockaddr*) &remoteaddr), remoteIP, INET6_ADDRSTRLEN), newfd));
					}

				} else {

					header_t header;
					initHeader(&header);

					log_info(LOGGER, "Esperamos recibir mensajes de los Jobs");
					if(recibir_header_simple(i, &header) != EXITO){
						log_error(LOGGER, "Error al recibir header. Considero que viene de un cliente que se cayó");
						header.tipo = ERR_CONEXION_CERRADA;
					}
					log_info(LOGGER, "Mensaje recibido! Header: %s", getDescription(header.tipo));

					switch(header.tipo){

						case ERR_CONEXION_CERRADA:
							close(i);
							FD_CLR(i, &master);
							job_eliminar(i, header);
							break;

						case JOB_TO_MARTA_FILES:
							// agrego el job a la lista sincronizada, gestiono las estructuras y blah
							job_agregar(i, header);
							// le pido al fs los bloques de los archivos del job y actualizo el job de la lista
							procesarArchivos(i, header);
							break;

						case JOB_TO_MARTA_MAP_OK:
							notificarMapOk(i, header);
							break;

						case JOB_TO_MARTA_MAP_ERROR:
							notificarMapError(i, header);
							break;

						case JOB_TO_MARTA_REDUCE_OK:
							notificarReduceOk(i, header);
							break;

						case JOB_TO_MARTA_REDUCE_ERROR:
							notificarReduceError(i, header);
							break;

						default: log_error(LOGGER, "ERROR mensaje NO RECONOCIDO (%d) !!\n",  header);
					}
				}
			}
		}
	}
}