void crearCaja(char ** caja){ //CREA LA UNIDAD CAJA Y LA ENGANCHA EN LA LISTA DE RECURSOS DEL NIVEL pthread_mutex_lock(&mutex_listas); CrearCaja(items, caja[1][0],atoi(caja[3]), atoi(caja[4]), atoi(caja[2])); pthread_mutex_unlock(&mutex_listas); pthread_mutex_lock(&mutex_log); log_info(logger, "Se crea la caja de %s", caja[1]); pthread_mutex_unlock(&mutex_log); }
void crearCajasConVector(char** array) { char id = array[1][0]; int instancia = atoi(array[2]); int pos_x = atoi(array[3]); int pos_y = atoi(array[4]); if (pos_x <= col && pos_y <= fil) { CrearCaja(listaRecursos, id, pos_x, pos_y, instancia); log_info(logFile, "Se creo la caja:%c, cantidad:%d, Pos:(%d,%d)", id, instancia, pos_x, pos_y); } else { log_warning(logFile, "No se creo la caja:%c, cantidad:%d, Pos:(%d,%d), sobrepasa los limites", id, instancia, pos_x, pos_y); } }
ITEM_NIVEL* crearNivel(nivelConfigStruct nivel) { ITEM_NIVEL* ListaItems = NULL; int32_t i; cajaStruct *caja; int32_t r,c; nivel_gui_inicializar(); nivel_gui_get_area_nivel(&r, &c); rows = r; cols = c; for (i = 0; i < list_size(nivel.cajas) ; i++) { caja = list_get(nivel.cajas,i); CrearCaja(&ListaItems,caja->simbolo,caja->posX,caja->posY,caja->instancias); } return ListaItems; }
t_nivel* configuracion_inicializar(char* path) { t_nivel* nivel = malloc(sizeof(t_nivel)); nivel->lista_items = NULL; t_config* configuracion_nivel = config_create(path); //nombre nivel->nombre = string_duplicate( config_get_string_value(configuracion_nivel, "Nombre")); //deadlock nivel->deadlock = config_get_int_value(configuracion_nivel, "TiempoChequeoDeadlock"); //recovery nivel->recovery = config_get_int_value(configuracion_nivel, "Recovery"); //ip y puerto char* ip_puerto = config_get_string_value(configuracion_nivel, "orquestador"); char**ip = string_split(ip_puerto, ":"); strcpy(nivel->ip, ip[0]); //puerto char* puerto = ip[1]; nivel->puerto = atoi(puerto); free(ip[0]); free(ip[1]); free(ip); //ip y puerto del nivel todo get ip char* ip_puerto_nivel= config_get_string_value(configuracion_nivel, "ip_nivel"); char**ip_nivel = string_split(ip_puerto_nivel, ":"); strcpy(nivel->ip_nivel, ip_nivel[0]); //puerto char* puerto_nivel = ip_nivel[1]; nivel->puerto_nivel = atoi(puerto_nivel); free(ip_nivel[0]); free(ip_nivel[1]); free(ip_nivel); //cantidad de key en el archivo, que son de cajas nada mas, resto 6 por ahora cantidad_key = config_keys_amount(configuracion_nivel) - 5; //los numeros de caja empiezan de 1 y van en orden(siempre) int count; for (count = 1; count <= cantidad_key; count++) { //armo las keys de las cajas char* key = string_from_format("Caja %d", count); if (config_has_property(configuracion_nivel, key)) { char* caja = (char*) config_get_string_value(configuracion_nivel, key); char** array_values = string_split(caja, ","); //del array saco el char del string que me viene char id = array_values[1][1]; CrearCaja(&(nivel->lista_items), id, atoi(array_values[3]), atoi(array_values[4]), atoi(array_values[2])); } } config_destroy(configuracion_nivel); nivel->personajes_deadlock = list_create(); log_info(logger, "se ha inicializado un nivel"); return nivel; }
int main(int argc, char* argv[]) { // Lo puse t0d0 en el llamado de abajo, no se porque y si se puede capturar 2 veces la señal como estaba hecho. // signal(SIGINT, notificarPersonajes); pthread_mutex_init(&semNiv, NULL); logger = logInit(argv, argv[1]); // Capturamos sigint y avisamos a los personajes para que cierren y cerramos el nivel. signal(SIGINT, cerrarForzado); t_config *configNivel; char** arrCaja; char* nom_nivel; char* ip_orq; char* port_orq; char* dir_orq; char ip[16]; int puerto; //--Creamos el config configNivel = config_try_create( //"nivel1.config" //Modo Debug argv[1], "Nombre,orquestador,TiempoChequeoDeadlock,Recovery,ip,puerto,Caja1"); ITEM_NIVEL *ListaItems = NULL; //--Creamos cada caja de recursos char* cajaAux; cajaAux = malloc(sizeof(char) * 6); sprintf(cajaAux, "Caja1"); //--Inicializa la lista con los personajes y sus recursos personajes = list_create(); personaje_t pjAux; int t = 1; int cols = 0; int rows = 0; int posXCaja = 0; int posYCaja = 0; nivel_gui_inicializar(); // Conseguimos el area del nivel char state = nivel_gui_get_area_nivel(&cols, &rows); // Validamos que no haya habido error if (state != EXIT_SUCCESS) { cerrarNivel("Error al intentar conseguir el area del nivel (GUI)."); exit(EXIT_FAILURE); } char* messageLimitErr; messageLimitErr = malloc(sizeof(char) * 100); //--Mientras pueda levantar el array while ((arrCaja = config_try_get_array_value(configNivel, cajaAux)) != NULL ) { posXCaja = atoi(arrCaja[3]); posYCaja = atoi(arrCaja[4]); // Validamos que la caja a crear esté dentro de los valores posibles del mapa if (posXCaja > rows || posYCaja > cols || posXCaja < 1 || posYCaja < 1) { sprintf(messageLimitErr, "La caja %c excede los limites de la pantalla. (%d,%d) - (%d,%d)", arrCaja[1][0], posXCaja, posYCaja, rows, cols); cerrarNivel(messageLimitErr); exit(EXIT_FAILURE); } // Si pasó la validacion, la creamos. CrearCaja(&ListaItems, arrCaja[1][0], atoi(arrCaja[3]), atoi(arrCaja[4]), atoi(arrCaja[2])); //--Rearma el cajaAux para la iteracion sprintf(cajaAux, "Caja%d", ++t); } free(cajaAux); //--Boludeces de los sockets message_t message; fd_set master, temp; struct sockaddr_in myAddress; struct sockaddr_in remoteAddress; int maxSock; int sockListener; int sockOrq; //--Saludo al orquestador //--Obetenemos el string del nombre y dirección del orquestador nom_nivel = config_get_string_value(configNivel, "Nombre"); dir_orq = config_get_string_value(configNivel, "orquestador"); puerto = config_get_int_value(configNivel, "puerto"); memcpy(ip, config_get_string_value(configNivel, "ip"), 16); // Conseguimos el tiempo de espera de chequeo int tiempoChequeo = config_get_int_value(configNivel, "TiempoChequeoDeadlock"); ip_orq = strtok(dir_orq, ":"); //--Separar ip port_orq = strtok(NULL, ":"); //--Separar puerto // Crear un socket: struct sockaddr_in socketInfo; if ((sockOrq = socket(AF_INET, SOCK_STREAM, 0)) != 0) { socketInfo.sin_family = AF_INET; socketInfo.sin_addr.s_addr = inet_addr(ip_orq); socketInfo.sin_port = htons(atoi(port_orq)); // Conectar el socket con la direccion 'socketInfo'. if (connect(sockOrq, (struct sockaddr*) &socketInfo, sizeof(socketInfo)) == -1) { perror("Connect"); exit(EXIT_FAILURE); } log_info(logger, "Conexión con orquestador."); orq_t orqMsj; orqMsj.type = NIVEL; orqMsj.detail = SALUDO; strcpy(orqMsj.name, nom_nivel); //memcpy(orqMsj.ip, &localhost->sin_addr.s_addr, 16); strcpy(orqMsj.ip, ip); orqMsj.port = puerto; //--Envía el "Saludo" para ser agregado if (send(sockOrq, &orqMsj, sizeof(orq_t), 0) == -1) { perror("Saludo"); exit(EXIT_FAILURE); } } // Definimos los threads pthread_t thr_interbloqueos; paramInterbloqueo_t parametros; parametros.numSock = sockOrq; parametros.tiempoChequeo = tiempoChequeo; parametros.recovery = config_get_int_value(configNivel, "Recovery"); // y los lanzamos if (pthread_create(&thr_interbloqueos, NULL, (void*) detectInterbloqueos, (void *) ¶metros)) { log_error(logger, strerror(errno)); exit(EXIT_FAILURE); } int maxRows, maxCols; int posX, posY; int posItemY, posItemX; int i; nivel_gui_get_area_nivel(&maxRows, &maxCols); nivel_gui_dibujar(ListaItems, nom_nivel); iniSocks(&master, &temp, &myAddress, remoteAddress, &maxSock, &sockListener, puerto, logger); while (1) { //--Gestiona un cliente ya conectado i = getSockChanged(&master, &temp, &maxSock, sockListener, &remoteAddress, &message, sizeof(message_t), logger); if (i != -1) { pthread_mutex_lock(&semNiv); int contPj; int contRec; char *auxRec; personaje_t *tempAux; //--Recibe mensaje y define comportamiento según el tipo switch (message.type) { case SALUDO: //--Agregamos personaje a la lista de items y a la de personajes/recursos CrearPersonaje(&ListaItems, i, message.name, INIX, INIY); pjAux.numSock = i; pjAux.chirimbolo = message.name; pjAux.blocked = false; pjAux.recursos = list_create(); list_add_new(personajes, &pjAux, sizeof(personaje_t)); //--Armamos la estrucura para enviar la posición inicial message.type = SALUDO; message.detail = INIX; message.detail2 = INIY; log_info(logger, "Se agregó el personaje %c con el socket %d", message.name, i); if (send(i, &message, sizeof(message), 0) == -1) perror("Respuesta posición inicial"); break; case POSICION: //--Obtiene posición del item pedido getPosRec(ListaItems, message.detail, &posX, &posY); //--Armamos la estrucura para enviar la posición del recurso pedido message.type = POSICION; message.detail = posX; message.detail2 = posY; if (send(i, &message, sizeof(message), 0) == -1) perror("Respuesta posición recurso"); break; case MOVIMIENTO: //--Devuelve las posiciones X e Y del item if (getPosPer(ListaItems, i, &posX, &posY) == -1) perror("GetPosItem"); switch (message.detail) { case ARRIBA: if (posY > 1) posY--; break; case ABAJO: if (posY < maxRows) posY++; break; case IZQUIERDA: if (posX > 1) posX--; break; case DERECHA: if (posX < maxCols) posX++; break; } //--Define confirmación y la devuelve message.type = MOVIMIENTO; message.detail2 = message.detail; message.detail = 1; if (send(i, &message, sizeof(message), 0) == -1) perror("Confirmacion"); //--Desbloquear en caso de que esté bloqueado for (contPj = 0; contPj < list_size(personajes); contPj++) { tempAux = list_get(personajes, contPj); if (tempAux->numSock == i && tempAux->blocked) tempAux->blocked = false; } MoverPersonaje(ListaItems, i, posX, posY); break; case PEDIDO: //--Obtiene posición del item pedido y del personaje getPosRec(ListaItems, message.detail, &posItemX, &posItemY); getPosPer(ListaItems, i, &posX, &posY); //--Valida si llegó al recurso if ((posItemX == posX) && (posItemY == posY)) { //-- Siempre le tiene que agregar a la lista de recursos, este o no bloqueado //--Agrega el recurso a la lista de recursos del personaje int contPj; personaje_t* tempAux; for (contPj = 0; contPj < list_size(personajes); contPj++) { tempAux = list_get(personajes, contPj); if (tempAux->numSock == i) { list_add_new(tempAux->recursos, &(message.detail), sizeof(message.detail)); break; } } //--Resta uno a la cantidad del item int result = restarQuantityRec(ListaItems, message.detail); if (result >= 0) { log_info(logger, "A %d se le da el recurso %c", i, message.detail); //--Si pudo restar la cantidad tempAux->blocked = false; //--Define confirmación y la devuelve message.detail = 1; if (send(i, &message, sizeof(message), 0) == -1) perror("Confirmacion"); } else { //--Si el recurso ya no tiene instacias tempAux->blocked = true; log_info(logger, "A %d se le niega el recurso %c", i, message.detail); //--Define rechazo y lo devuelve message.detail = 0; if (send(i, &message, sizeof(message), 0) == -1) perror("Confirmacion"); } } else { log_error(logger, "Posicion erronea al pedir recurso"); exit(EXIT_FAILURE); } break; case SALIR: for (contPj = 0; contPj < list_size(personajes); contPj++) { tempAux = list_get(personajes, contPj); if (tempAux->numSock == i) { //--Elimina y libera la lista de recursos de personaje for (contRec = 0; contRec < list_size(tempAux->recursos); contRec++) { auxRec = list_get(tempAux->recursos, contRec); //--Suma la cantidad de recursos que el personaje libera sumarQuantityRec(ListaItems, *auxRec, 1); } list_destroy_and_destroy_elements(tempAux->recursos, free); //--Elimina y libera al personaje de la lista de personajes list_remove_and_destroy_element(personajes, contPj, free); BorrarPer(&ListaItems, i); break; } } log_debug(logger, "%d se desconectó", i); break; } nivel_gui_dibujar(ListaItems, nom_nivel); pthread_mutex_unlock(&semNiv); } } nivel_gui_terminar(); return 0; }
void crearGuiRecursos(void* item) { DataRecurso* resource = (DataRecurso *) item; CrearCaja(&listaItems, resource->recurso->simbolo, resource->posicion.x, resource->posicion.y, resource->recurso->cantidad); }