Olivia_v2017/OliviaTasks/OlvTaskProcess.cpp

497 lines
13 KiB
C++
Raw Blame History

#include "StdAfx.h"
#include "OlvTaskProcess.h"
#include "olivia_def.h"
#include <sstream>
#include <string>
#include "olv_task.h"
#define MODULO "OlvTaskProcess"
std::string to_string(double& d)
{
char dig[256];
dig[0]=0;
return dig;
}
//*******************************************************************************************************
OlvTaskProcess::OlvTaskProcess(void)
{
costes.clear();
va_mal=FALSE;
angs=NULL;
}
OlvTaskProcess::~OlvTaskProcess( void )
{
costes.clear();
if(angs)
{
for(int i=0;i<info.n;i++)
{
angs[i].libera();
}
free(angs);
angs=NULL;
}
ia.clear();
cost_amb.clear();
}
//*******************************************************************************************************
void OlvTaskProcess::preTask()
{
//pilla informacion de socket necesaria
//el tread no esta currando
//presentacion-----------------------------------------
int aux[2];
aux[0]= PETICION_GENERAL_PRESENTA;
aux[1]=ithr;
if(!envia(aux,sizeof(aux)))
{
C_log::log(MODULO, "error al enviar presentacion");
cancela();
return;
}
int nb;
void *data = recibe(&nb);
if(nb < sizeof(int) || (*(int*)data)!=PETICION_GENERAL_OK)
{
C_log::log(MODULO, "error al recibir contestacion de presentacion");
cancela();
return;
}
data = recibe(&nb);
if(nb<sizeof(InfoIniTask))
{
C_log::log(MODULO, "error al recibir contestacion de presentacion");
cancela();
return;
}
memcpy(&info,data,sizeof(InfoIniTask));
//------------------------------------------------------
}
//*******************************************************************************************************
void OlvTaskProcess::inTask()
{
//envia sigue vivo----------------------
int aux = PETICION_GENERAL_OK;
if(!envia(&aux,sizeof(aux)))
{
C_log::log(MODULO, "error al enviar Ok");
cancela();
return;
}
int nb;
void *data = recibe(&nb);
if(nb<sizeof(int))
{
C_log::log(MODULO, "error al recibir contestacion ok");
cancela();
return;
}
//mira contstacion------------------------
switch(*(int*)data)
{
case(PETICION_GENERAL_OK):
break;
default://PETICION_GENERAL_NO
C_log::log(MODULO, "Recibida peticion de cancelacion");
cancela();
}
//envia log
enviaLog();
}
void OlvTaskProcess::enviaLog()
{
StrArray msgs;
if(OlvApp.colaLog.dame(msgs))
{
char buf[1028];
int *id =(int*) buf;
char* msg = (char*)&id[1];
*id = PETICION_GENERAL_DAME_LOG;
for (int i = 0; i<msgs.n_i; i++)
{
strcpy(msg,msgs.get(i));
if(!envia(&buf,(int)(sizeof(int)+strlen(msg)+1)))
{
C_log::log(MODULO, "error al enviar Log");
cancela();
}
}
}
}
//*******************************************************************************************************
void OlvTaskProcess::postTask()
{
enviaLog();
int aux[2];
aux[0]= PETICION_GENERAL_FIN;
if(va_mal)
{
aux[1]=PETICION_GENERAL_NO; //dependiendo del estado
}
else
{
aux[1]=PETICION_GENERAL_OK; //dependiendo del estado
C_log::log(MODULO,"Task %ld, Enviando final feliz",ithr);
}
if(!envia(aux,sizeof(aux)))
{
C_log::log(MODULO, "Task %ld, Error al enviar terminado",ithr);
cancela();
}
int nb;
void *data = recibe(&nb);
if(nb<sizeof(int)|| *(int*)data != PETICION_GENERAL_FIN)
{
C_log::log(MODULO, "Task %ld, Error al recibir fin",ithr);
}
}
//*******************************************************************************************************
void OlvTaskProcess::run()
{
//tarea a realizar
//lee archivos de costes, angulos e informacion asociada
//si !usa_angs, angs=NULL;
if(!lee_mats())
{
C_log::log(MODULO,"Task %ld,Error en lee_mats", ithr);
va_mal=TRUE;
goto sal;
}
if(!calcula_cost_ambThr())
{
C_log::log(MODULO,"Task %ld,Error en calcula_cost_amb_sub", ithr);
va_mal=TRUE;
goto sal;
}
//guarda mat de cost_amb
if(!guarda_cost_amb())
{
C_log::log(MODULO,"Task %ld,Error en guarda_cost_amb", ithr);
va_mal=TRUE;
goto sal;
}
sal:
C_log::log(MODULO, "Task de tarea saliendo %ld %s",ithr, va_mal ? "Mal" : "Bien");
}
//*******************************************************************************************************
BOOL OlvTaskProcess::calcula_cost_ambThr()
{
//inicializa archivo----------------------
char p[MAX_PATH];
BOOL mal=FALSE;
sprintf_s(p,MAX_PATH,"%s\\%s",info.path_temp,NOMB_ARCH_DIJ_DEF);
if(!arch_dj.inicia(p, TRUE,FALSE, info.n))
{
C_log::log(MODULO,"Task %ld,Error %ld no se ha podido crear ndj", ithr,GetLastError());
mal = TRUE;
goto final;
}
//C_log::log(MODULO,"sizeof %ld %ld %ld %ld", sizeof(Head_dj_arch),sizeof(Djkt_nodo), sizeof(Djkt_ids_pdr), arch_dj.sizn);
if(!arch_dj.inicia_inf_amb(&ia,info.namb,info.KK,info.id_instal, info.id_planta))
{
C_log::log(MODULO,"Task %ld,Error %ld no se ha podido crear info de ambitos", ithr,GetLastError());
mal = TRUE;
goto final;
}
//pilla memoria necesaria para coste de ambitos--------------
if(!cost_amb.inicia(info.namb,info.namb))
{
C_log::log(MODULO,"Task %ld,Error %ld no se ha podido iniciar cost_amb, sin memoria", ithr,GetLastError());
//sin memoria
mal = TRUE;
goto final;
}
for(int i = 0; i<info.namb; i++)
for(int j = 0; j<info.namb; j++)
cost_amb[i][j] = (float)MAYUSCULO;
//////////////////////////////////////
//lanza los threads
mal=lanza_thr_calc();
//////////////////////////////////////
//termina de guardar
if(!mal && !arch_dj.graba_dis(ithr))
{
C_log::log(MODULO,"Task %ld,Error %ld no se ha podido guardar la info de ambitos", ithr,GetLastError());
mal = TRUE;
}
final:
return !mal;
}
//*******************************************************************************************************
BOOL OlvTaskProcess::lanza_thr_calc()
{
ThCalcCostes th[MAX_THREAD_LEE];
int nth = min(info.nthr,MAX_THREAD_LEE);
int ntsk=(int)ceil(info.namb*1./(info.ntsks));
int n = (int)ceil(ntsk*1./(nth));
int asig = 0;
int i=0;
for(i=0; i<nth && asig<info.namb; i++)
{
th[i].ithr = i;
th[i].pclas = this;
th[i].mal = FALSE;
th[i].ini = i*n+ithr*ntsk;
th[i].fin = min((i+1)*n+ithr*ntsk,info.namb);
asig=th[i].fin;
th[i].lanza();
}
BOOL mal=FALSE;
for(int ic=0; ic<i; ic++)
{
th[ic].join();
mal|=th[ic].mal;
}
return mal;
}
//*******************************************************************************************************
void ThCalcCostes::run()
{
mal = FALSE;
if(!pclas->calcula_cost_amb_sub(ini,fin,ithr))
mal=TRUE;
}
//*******************************************************************************************************
BOOL OlvTaskProcess::calcula_cost_amb_sub(int amb_ini,int amb_fin, int ith)
{
int na,i,k;
int seg;
Djkt_nodo *costes_nodos;
BOOL mal=FALSE;
//----------------------------------------
////////////////
int na_desp = amb_fin-amb_ini;
costes_nodos=NULL;
////////////////
FlagsArray visto_ang;//buffer de flags
C_log::log(MODULO,"Subthr %ld, Ambs %04d a %04d, numero ambitos totales %ld", ith,amb_ini, amb_fin, info.namb);
seg = GetTickCount();
/////////////////////////////////////
//Bucle por cada <20>mbito de los que le tocan a este thread
/////////////////////////////////////
//el coste de un <20>mbito a s<> mismo es el de trabajar ese <20>mbito,
//que es el coste de ir de su conj inicial a la final
//na=na_ini;
/////////////////////////////////////
for(na=amb_ini;na<amb_fin && !pirate; na++)
{
//En olv_limp->ias[i].ic_ini est<73> almacenado el <20>ndice de la conjunci<63>n del nodo inicial del <20>mbito
//y en olv_limp->ias[i].ic_fin el del final. Se puede acceder con i directamente al array ias porque
//la info asociada est<73> a<>adida por orden, primero los <20>mbitos
/////////////////////////////////////////////
//calcula el coste m<>ximo del <20>mbito na a todos los dem<65>s
//los a<>ade a la fila na de la matriz de costes
//es coste m<>ximo porque hace el m<>ximo de:
//inicio(na)->inicio(ni), inicio(na)->final(ni), final(na)->inicio(ni), final(na)->final(ni)
/////////////////////////////////////////////
//k==0, calcula las distancias del nodo inicial de ese <20>mbito a todas las dem<65>s conjunciones
//k==1, calucla las distancias del nodo final
for(k=0;k<info.KK;k++)
{
costes_nodos=NULL;
if(!DijkstraUtiles::dijkstra_ang_inv_ok(costes, angs, info.n,
(1-k)*ia.get(na,0)+k*ia.get(na,1),
&costes_nodos, &visto_ang))
{
C_log::log(MODULO,"Subthr %ld,Error en dijkstra_ang_inv_ok", ith);
mal=TRUE;
break;
}
//recorre todos los dem<65>s <20>mbitos buscando el coste a ellos en el array de costes devuelto, y los almacena
//almacena el coste a su nodo inicial y a su nodo final
if(ia.getFlags(na) & OLV_LIMP_FLG_AMB_NO)
{
for (i=0; i<info.n; i++)
{
costes_nodos[i].dis=(float)MAYUSCULO;
costes_nodos[i].id_padre=-1;
costes_nodos[i].ids_ady.nady=0;
}
}
else
{
for(i=0;i<info.namb;i++)
{
if(ia.getFlags(i) & OLV_LIMP_FLG_AMB_NO)
continue;
if(na==i)
{
//el coste de un <20>mbito a s<> mismo es el de trabajar ese <20>mbito
cost_amb[na][na]=costes[ia.get(na,0)][ia.get(na,1)];
continue;
}
if(cost_amb[i][na]>costes_nodos[ia.get(i,0)].dis)
cost_amb[i][na]=costes_nodos[ia.get(i,0)].dis;
if(info.KK==OLV_AMB_LIN)
{
if(cost_amb[i][na]>costes_nodos[ia.get(i,1)].dis)
cost_amb[i][na]=costes_nodos[ia.get(i,1)].dis;
}
}
}
if(!arch_dj.add_b(costes_nodos, na, k, TRUE))
{
C_log::log(MODULO,"Subthr %ld,Error %ld no se ha podido guardar dj iref: %ld k: %ld", ith,
GetLastError(),na,k);
}
}
if(mal)
break;
//avisa de progreso
if(((na-amb_ini)%20==0))
{
C_log::log(MODULO,"Subthr %ld, Rellenando matriz de dist entre ambs %ld de %ld", ith,
(na-amb_ini+1),na_desp);
}
}
if(mal || pirate)
{
C_log::log(MODULO,"Subthr %ld, Error en c<>lculo de matriz de distancias entre <20>mbitos", ith);
return FALSE;
}
C_log::log(MODULO,"Subthr %ld, Fin Matriz de dist entre ambs, %.3f seg", ith, 1.0*(GetTickCount()-seg)/1000);
return TRUE;
/////////////////////////////////////
}
//*******************************************************************************************************
BOOL OlvTaskProcess::lee_mats()
{
//lee archivos de costes, angulos e informacion asociada
//si !usa_angs, angs=NULL;
BOOL mal=FALSE;
CoptiMemo oo(TRUE);
C_log::log(MODULO,"Task %ld, Memo disp %I64d",ithr, oo.memo);
int nvect=oo.calc_nvect_multi(info.n,info.nthr,sizeof(Djkt_elem_cola));
if(nvect<0)
{
C_log::log(MODULO,"Task %ld, Error sin memoria al calcular nvect",ithr);
goto va_mal;
}
C_log::log(MODULO,"Task %ld, Calculando con nvect %ld de %ld",ithr, nvect,info.n);
//inicializa los arrays
costes.inicializa(info.n,info.nthr,nvect);
C_log::log(MODULO,"Task %ld, Lee matriz de costes",ithr);
if(!costes.leeThread(info.path_cconj,info.ext,info.nthr,FALSE)) //el false es para forzar a que todos sean vect, que no los haga igual que los archivos
{
C_log::log(MODULO,"Task %ld, Error al leer matriz de costes: %s",ithr, info.path_cconj );
goto va_mal;
}
C_log::log(MODULO,"Task %ld, Lee matriz de angulos",ithr);
if(info.usa_angs)
{
angs = new Djkt_ang_ady[info.n];
if(!angs)
{
C_log::log(MODULO,"Task %ld, Error lee_mat sin memoria para %ld Djkt_ang_ady",ithr, info.n);
mal=TRUE;
}
for(int ic=0; ic<info.n && !mal; ic++)
{
if(!angs[ic].lee(ic,info.path_ang,info.ext))
{
C_log::log(MODULO,"Task %ld,Error en lee_mats", ithr);
mal=TRUE;
}
}
if(mal)
{
C_log::log(MODULO,"Task %ld, Error al leer matriz de angulos: %s",ithr, info.path_ang );
goto va_mal;
}
}
C_log::log(MODULO,"Task %ld, Lee informacion asociada",ithr);
if(!ia.leeFile(info.file_iaso))
{
C_log::log(MODULO,"Proceso %ld, Error al leer matriz de info aso: %s",ithr, info.file_iaso );
goto va_mal;
}
return TRUE;
va_mal:
return FALSE;
}
//*******************************************************************************************************
BOOL OlvTaskProcess::guarda_cost_amb()
{
C_log::log(MODULO,"Task %ld, Guardando costes entre ambitos",ithr);
char path[MAX_PATH];
sprintf_s(path,MAX_PATH,"%s%02d.%s",info.path_costamb,ithr,info.ext);
if(!Cdir_manager::crea_dir(info.path_costamb)||!cost_amb.graba(path))
{
C_log::log(MODULO,"Task %ld, Error al guardar matriz de costes de ambitos: %s",ithr,path);
return FALSE;
}
return TRUE;
}
//*******************************************************************************************************
void OlvTaskProcess::desconecta()
{
OlvApp.isConnected = FALSE;
TaskProcess::desconecta();
}
//*******************************************************************************************************
BOOL InfoIndiceEx::leeFile( char* path )
{
Cb_file file;
dat.borra();
if(!file.abre(path,1,FALSE,TRUE))
{
C_log::log(MODULO,"Error en apertura de archivo InfoIndiceEx::leeFile: %s", path);
return false;
}
if(!dat.leer(&file))
{
C_log::log(MODULO,"Error en lectura de archivo InfoIndiceEx::leeFile: %s", path);
return false;
}
return TRUE;
}
//*******************************************************************************************************