t_queue* enviarRecursoOrquestador(recursosPersonajesStruct *unPersonaje)
{
        t_log *log = log_create(logName,"Nivel",FALSE,LOG_LEVEL_INFO);
        int32_t length,size;
        liberadosNoSerializadoStruct colaLib;
        colaNoSerializadaStruct *colaAsig;
        nivelYPersonaje nivelYPersonaje;
        colaLib.cola=unPersonaje->recursos;
        void *data = serializador_liberados(&colaLib,&size);
        length = size + sizeof(header_t);

        int32_t socketOrquestador = socketCreateClient(getIp(nivel.orquestador), getPort(nivel.orquestador));


        nivelYPersonaje.personaje = unPersonaje->simbolo;
        strcpy(nivelYPersonaje.nivelNombre,nivel.nombre);

        socketSend(socketOrquestador, data, length);
        socketSend(socketOrquestador, &(nivelYPersonaje), sizeof(char[30]));

        recv(socketOrquestador,&length,sizeof(int32_t),MSG_WAITALL);
        void *buffer = malloc(length);
        recv(socketOrquestador,buffer,length,MSG_WAITALL);
        colaAsig = desserializador_recursos(buffer);

        shutdown(socketOrquestador,2);
        log_destroy(log);
        return colaAsig->cola;
}
void detectarYMatarPersonaje(t_queue *cola,nivelPlanificadorStruct *nivel)
{
        t_log *log = log_create("Plataforma.log","Orquestador",true,LOG_LEVEL_INFO);
        simboloStruct *unSimbolo;
        listaPersonajesStruct *unPersonaje,*min;
        int32_t orden = 0;
        mensajePersonaje id;
        int socketNivel;
        id.idMensaje=4;

        while (!queue_is_empty(cola))
        {
                unSimbolo = queue_pop(cola);

                bool condicion(void* personaje)
                {
                        return (((listaPersonajesStruct*) personaje)->simbolo == unSimbolo->simbolo);
                }

                log_info(log,"Personaje en Interbloqueo: %c",unSimbolo->simbolo);
                unPersonaje = (listaPersonajesStruct *) list_find(nivel->listaPersonajes,condicion);
                if ((unPersonaje->ordenDeEntrada < min->ordenDeEntrada) || (orden == 0))
                {
                        min=unPersonaje;
                        orden = 1;
                }


        }
        log_info(log,"%s llego tu hora de morir",min->nombre);
        socketSend(min->descriptorPersonaje,&id,sizeof(mensajePersonaje));

        //log_info(nivel->log,"Mate a %s por Interbloqueo",min->nombre);
        sacarDeCola(nivel->bloqueados,min,'B',nivel->log,&(nivel->semColas)); //Esto es lo ultimo que agregamos. Ver si no perjudica en otro caso!!



        socketNivel = socketCreateClient(nivel->ipNivel, nivel->puertoNivel);
        personajeQueMurioStruct *identificador = malloc(sizeof(personajeQueMurioStruct));
		identificador->id=3;
		identificador->simbolo=min->simbolo;
		socketSend(socketNivel,identificador,sizeof(personajeQueMurioStruct));
		free(identificador);
		log_destroy(log);

}
int main(int argc, char** argv) {

	if(argc != 2){
		puts("No se ingreso la ruta del archivo de configuracion\n");
		return 0;
	}

	thread_socket= 3030;
	paginaEncontrada=TRUE;
	umclog=malloc(sizeof(t_log));
	memcpy(umclog,log_create("umc.log", "UMC", TRUE, LOG_LEVEL_TRACE), sizeof(t_log));

	leerArchivoDeConfiguracion(argv[1]);
	crearLogger(0);
	log_info(umclog, "Inicio UMC.");

	pthread_t hiloComandos;
	pthread_attr_t attrhiloComandos;

	memoriaReal = reservarMemoria(marcos, marco_Size); //Fabrico mi memoria real

	iniciarEstructurasUMC();

	socketSwap=socketCreateClient();

	socketConnect(socketSwap,ip_Swap,atoi(puerto_Swap));

	menuUMC(hiloComandos, attrhiloComandos);

	manageSocketConnections();


	liberarMemoria(memoriaReal); //Una vez terminado, libero toda mi memoria real
	log_destroy(logger);

	return EXIT_SUCCESS;

}
void algoritmoInterbloqueo(int32_t numeroPersonajes)
{
	t_log *log = log_create(logName,"Nivel",FALSE,LOG_LEVEL_INFO);
	t_log *log2 = log_create("matriz.log","matriz",FALSE,LOG_LEVEL_INFO);
	t_list *peticionesActuales, *asignados,*disponibles,*simbolosPersonajes;
	t_list *peticionesPorProceso,*procesoAsignados;
	simboloStruct *unSimbolo;
	void* buffer;
	int32_t nProcesos;
	int32_t socketOrquestador;
	int32_t nRecursos = list_size(nivel.cajas);
	int32_t i;
	colaNoSerializadaStruct colaInterbloqueo;
    int32_t length;
    int16_t size=0;
	unRecursoPaquetizadoStruct *instanciasDisponibles,*instanciasPedidas,*instanciasAsignadas;
	int32_t aux= TRUE, proc,r;
	t_queue *enInterbloqueo;
	if (!listaPersonajes)
			listaPersonajes = list_create();
	nProcesos = numeroPersonajes;
	if (nProcesos > 0)
	{
		disponibles=obtenerMatrizDisponibles();
		asignados=obtenerMatrizAsignados(listaPersonajes,numeroPersonajes);
		peticionesActuales=obtenerPeticionesActuales(listaPersonajes,numeroPersonajes);
		simbolosPersonajes=obtenerListaSimbolos(listaPersonajes,numeroPersonajes);
		mostrarMatrizPeticiones(peticionesActuales,simbolosPersonajes);
		mostrarMatrizASIG(asignados,simbolosPersonajes);
		disponiblesMatriz(disponibles);

		//elimino los que no tienen asignados
		for (proc = 0; proc < nProcesos; proc++)
		{

				procesoAsignados = (t_list *) list_get(asignados,proc);
				 bool condicionCeros(void* recurso) {
						return (((unRecursoPaquetizadoStruct *) recurso)->recurso != 0);
				 }

				if ( list_size(list_filter(procesoAsignados,condicionCeros)) == 0 )
				{
						list_remove_and_destroy_element(peticionesActuales,proc,element_destroyer);
						list_remove_and_destroy_element(asignados,proc,element_destroyer);
						unSimbolo = list_remove(simbolosPersonajes,proc);
						free(unSimbolo);
						nProcesos--;
						proc--;
				}

		}

		aux = TRUE;
		proc = 0;
		if (nProcesos > 0)
		{
			for (proc = 0; proc < nProcesos; proc++ )
		    {
				log_info(log2,"Chequeando proceso %c",((simboloStruct *) list_get(simbolosPersonajes,proc))->simbolo);

			    aux = TRUE;
			    //lista de un solo proceso (como si fuera un arreglo)
			    peticionesPorProceso = (t_list *) list_get(peticionesActuales,proc);
			    procesoAsignados = (t_list *) list_get(asignados,proc);

			    for (r=0; r < nRecursos; r++)
			    {
					instanciasDisponibles = (unRecursoPaquetizadoStruct *) list_get(disponibles,r);
					instanciasPedidas = (unRecursoPaquetizadoStruct *) list_get(peticionesPorProceso,r);
					instanciasAsignadas = (unRecursoPaquetizadoStruct *) list_get(procesoAsignados,r);
					// comprobamos que haya recursos suficientes
					aux = (instanciasPedidas->recurso - instanciasDisponibles->recurso) <= 0;
					if (!aux)
					{
							log_info(log2,"%c todavia necesita %d instancias de %c",((simboloStruct *) list_get(simbolosPersonajes,proc))->simbolo,instanciasPedidas->recurso,((cajaStruct *)list_get(nivel.cajas,r))->simbolo);
							log_info(log2,"hay %d instancias",instanciasDisponibles->recurso);
							break;
					}
			    }

			    if (aux)
			    {
					log_info(log2,"suponemos que %c termina",((simboloStruct *) list_get(simbolosPersonajes,proc))->simbolo);
					aniadirYeliminar(disponibles, asignados, proc);
					//remover indice de maximos

					list_remove_and_destroy_element(peticionesActuales,proc,element_destroyer);
				    unSimbolo = list_remove(simbolosPersonajes,proc);
				    free(unSimbolo);
				    nProcesos--;
				    proc = -1;
				    if (nProcesos == 0)
				    {
						log_info(log,"Es estado seguro");
						log_info(log2,"Es estado seguro");
						log_destroy(log);
						log_destroy(log2);
						list_destroy(disponibles);
						list_destroy(asignados);
						list_destroy(peticionesActuales);
						list_destroy(simbolosPersonajes);
						return;
				    }
			    }
			}
		    log_info(log,"Es Interbloqueo");
		    log_info(log2,"Es Interbloqueo");

		    for (i=0 ; i < list_size(simbolosPersonajes) ; i++)
						   log_info(log,"Personaje en interbloqueo: %c",((simboloStruct *) list_get(simbolosPersonajes,i))->simbolo);

		    if (nivel.recovery == 1)
		    {

				   enInterbloqueo=queue_create();
				   socketOrquestador = socketCreateClient(getIp(nivel.orquestador), getPort(nivel.orquestador));

				   for (i=0 ; i < list_size(simbolosPersonajes) ; i++)
				   {
						   queue_push(enInterbloqueo,list_get(simbolosPersonajes,i));
				   }
				   colaInterbloqueo.cantidadPersonajes=list_size(simbolosPersonajes);
				   colaInterbloqueo.cola = enInterbloqueo;
				   buffer = serializador_interbloqueo(&colaInterbloqueo,&size);
				   length = size + sizeof(header_t);
				   socketSend(socketOrquestador,buffer,length);
				   socketSend(socketOrquestador, &(nivel.nombre), sizeof(char[30]));
				   shutdown(socketOrquestador,2);
				   queue_destroy(enInterbloqueo);
				   free(buffer);
		    }
	    }
		list_destroy(disponibles);
		list_destroy(asignados);
		list_destroy(peticionesActuales);
		list_destroy(simbolosPersonajes);
	}
//testeada
int inicializarVariables(char* ruta) {

	// LOG
	nucleolog = malloc(sizeof(t_log));
	//nucleolog = log_create("nucleo.log", "NUCLEO", 1, LOG_LEVEL_INFO);

	memcpy(nucleolog, log_create("nucleo.log", "NUCLEO", 1, LOG_LEVEL_INFO),
			sizeof(t_log));

	//tamanioPaginas=pedirTamanioDePagina();

	//Variables de lectura de archivo
	puertoPropio = (char*) malloc(sizeof(puertoPropio));
	cpuPort = (char*) malloc(sizeof(cpuPort));
	quantum = (int) malloc(sizeof(quantum));
	quantumSleep = (int) (sizeof(quantumSleep));
	idSemaforos = (char**) malloc(sizeof(idSemaforos));
	viSemaforos = (char**) malloc(sizeof(viSemaforos));
	cantSemaforos = (int) malloc(sizeof(cantSemaforos)); //No se lee por config
	idIO = (char**) malloc(sizeof(idIO));
	retardoIO = (char**) malloc(sizeof(retardoIO));
	int cantIO = (int) malloc(sizeof(cantIO));	//No se lee por config

	idVariableCompartida = (char**) malloc(sizeof(idVariableCompartida));
	cantVarCompartidas = (int) malloc(sizeof(cantVarCompartidas));
	//variableCompartidaValor=(int*)malloc(sizeof(variableCompartidaValor));
	ipUMC = (char*) malloc((sizeof(ipUMC)));
	UMCPort = (char*) malloc((sizeof(UMCPort)));
	stackSize = (int) malloc((sizeof(stackSize)));
	tamanioPaginas = (int) malloc((sizeof(tamanioPaginas)));

	//Otras Variables
	idProgramas = (int) malloc(sizeof(idProgramas)); //Contador de programa
	primeraLectura = (bool) malloc(sizeof(primeraLectura));

	//Sincronizacion
	//pthread_mutex_t** mutexIO;
	//pthread_mutex_t** mutexVariables;
	mutexQuantum = malloc(sizeof(pthread_mutex_t));

	mutexColaNew = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
	mutexColaReady = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
	mutexColaExit = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
	mutexListaExec = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
	mutexListaBlock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
	mutexListaCpu = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));

	primeraLectura = true;

	int i;

	//Leo el archivo de configuracion
	leerArchivoDeConfiguracion(ruta);

	//Inicio Semaforos
	cantSemaforos = cantidadPalabrasEnArrayDeStrings(idSemaforos);
	char* valorInicial;
	//char algo;
	unsigned int algo2 = 0;

	//sem_t semaforoPrueba;
	//sem_init(&semaforoPrueba, 0, 4);

	//semaforosAnsisop=malloc(sizeof(pthread_mutex_t)*cantSemaforos);

	for (i = 0; i < cantSemaforos; i++) {
		valorInicial = viSemaforos[i];
		//algo=*valorInicial;
		algo2 = atoi(valorInicial);
		semaforosAnsisop[i] = malloc(sizeof(sem_t));
		if (sem_init((semaforosAnsisop[i]), 0, algo2) != 0) {
			printf("\n init semaforoAnsisop %d fallo\n", i);
			return -1;
		}
	}

	//Inicio Semaforos de Sincro

	//inicio cantIO
	cantidadDispositivosIO = malloc(sizeof(int));
	cantIO = cantidadPalabrasEnArrayDeStrings(idIO);
	memcpy(cantidadDispositivosIO,&cantIO,sizeof(int));
	//mutexIO=malloc(sizeof(pthread_mutex_t)*cantIO);

	for (i = 0; i < cantIO; i++) {

		mutexIO[i] = malloc(sizeof(pthread_mutex_t));
		if (pthread_mutex_init(mutexIO[i], NULL) != 0) {
			printf("\n init mutexIO %d fallo\n", i);
			return -1;
		}
	}

	//inicio cantVarsCompartidas
	cantVarCompartidas = cantidadPalabrasEnArrayDeStrings(idVariableCompartida);

	variableCompartidaValor = (int*) malloc(sizeof(int) * cantVarCompartidas);

	for (i = 0; i < cantVarCompartidas; i++) {
		variableCompartidaValor[i] = 0;
	}
	//mutexVariables=malloc(sizeof(pthread_mutex_t)*cantVarCompartidas);
	for (i = 0; i < cantVarCompartidas; i++) {
		mutexVariables[i] = malloc(sizeof(pthread_mutex_t));
		if (pthread_mutex_init(mutexVariables[i], NULL) != 0) {
			printf("\n init mutexVariables %d fallo\n", i);
			return -1;
		}
	}

	if (pthread_mutex_init(mutexListaCpu, NULL) != 0) {
		printf("\n init mutexListaCpu fallo\n");
		return -1;
	}

	if (pthread_mutex_init(mutexQuantum, NULL) != 0) {
		printf("\n init mutexQuamtum fallo\n");
		return -1;
	}

	if (pthread_mutex_init(mutexColaNew, NULL) != 0) {
		printf("\n init mutexCOlaNew fallo\n");
		return -1;
	}
	if (pthread_mutex_init(mutexColaReady, NULL) != 0) {
		printf("\n init mutexColaReady fallo\n");
		return -1;
	}
	if (pthread_mutex_init(mutexColaExit, NULL) != 0) {
		printf("\n init mutexColaExit fallo\n");
		return -1;
	}
	if (pthread_mutex_init(mutexListaBlock, NULL) != 0) {
		printf("\n init mutexListaBlock fallo\n");
		return -1;
	}
	if (pthread_mutex_init(mutexListaExec, NULL) != 0) {
		printf("\n init mutexListaExec fallo\n");
		return -1;
	}

	//inicio El contador de ids
	idProgramas = 0;

	//InicioLasColas
	listaNew = list_create();
	//colaNew = queue_create();
	listaReady = list_create();
	//colaReady = queue_create();
	listaExec = list_create();
	listaBlock = list_create();
	listaExit = list_create();
	//colaExit = queue_create();
	listaCpu = list_create();

	umcServer = socketCreateClient();
	do {
		puts("**********************************");
		puts("Intentando conectar con la UMC ppal.");
		printf("IP: %s, PUERTO: %d\n", ipUMC, atoi(UMCPort));
		sleep(3);
	} while (!socketConnect(umcServer, ipUMC, atoi(UMCPort)));
	StrKerUmc* out_umc_msg = newStrKerUmc(KERNEL_ID, HANDSHAKE, NULL, 0, 0, 0,
			0, 0, 0);
	SocketBuffer* sb = serializeKerUmc(out_umc_msg);
	socketSend(umcServer->ptrSocket, sb);
	puts("Mensaje enviado a la UMC ppal.");

	sb = socketReceive(umcServer->ptrSocket);
	StrUmcKer* in_umc_msg = unserializeUmcKer(sb);

	printf("Nuevo UMC es %d.\n", in_umc_msg->size);

	int nuevoPuertoUmc = in_umc_msg->size;
	tamanioPaginas = pedirTamanioDePagina(nuevoPuertoUmc);

	return 0;
}