unit uFichaNodo;

interface

uses
  xMatDefs, classes, sysutils, uconstantes_nettopos,
{$IFDEF WINDOWS}
  Windows,
{$ELSE}
  timeLib,
{$ENDIF}
{$IFDEF NETTOPOS_DLL}
  uimportnettopos,
{$ELSE}
  unettopos,
  unettopostypes,
  uglobsharedmem
{$ENDIF};

type
  TServicioEnEjecucion = class
    public
      nombreServicio: String;
      idAplicacion: Cardinal;

      Constructor Create(nombreServicio: String; idAplicacion: Cardinal);
      procedure dumpToText(var f: TextFile; strIndentacion: String);
  end;

  {Calculo de velocidad:
    la velocidad de un nodo se define como el promedio de los pesos relativos
    de las tareas que ejecuto sobre el tiempo que le llevo ejecutarlas
    para n mediciones vn = (sum(i=1..n)(pi / ti)) / n

    para que esta medicion sea representativa debe realizarse reiteradas veces
    sobre operaciones de duración similar
    para el caso en que el tiempo depende de una única operación se provee la clase
    TTemporizadorUniOperacion que realiza el promedio mencionado

    en el caso de que la operación a la cual se le va a medir la velocidad este
    compuesta de varias operaciones se puede implementar una clase
    TTemporizadorMultiOperacion que realice el siguiente promedio
    para n mediciones vn = (sum(i=1..n)((sum(j=1..k)(pj/tj)) / ti)) / n
    donde k es el numero de subtareas que componen la tarea principal
    el temporizador debería guardar cada pj/tj y al actualizar la velocidad
    realizar el correspondiente promedio
    }
  TFichaNodo = class
    public
      nombre: String;
      idNodo, idTopo: Cardinal;

      dtVencimientoGlobal: Int64; //La fecha en que vence la lista de tareas
                                     //de la tarea que este ejecutando el nodo
      dtUltimoPedido: Int64; //La fecha en que se le hizo el ultimo pedido
                                //al nodo
      velocidad: NReal;

      listaServicios: TList{Of TServicioEnEjecucion};
      nVecesConsecutivasQueNoRespondio: Integer; //Se van asignando tareas al nodo.
                                                 //Si no responde en tantas veces se lo echa

      Constructor Create(idNodo, idTopo: Cardinal; nombreNodo: String);
      function idServicio(nombreServicio: String): Cardinal;
      procedure quitarServicio(nombreServicio: String);
      procedure dumpToText(var f: TextFile; strIndentacion: String);
  end;

implementation

//===============================
//Métodos de TServicioEnEjecucion
//-------------------------------

Constructor TServicioEnEjecucion.Create(nombreServicio: String; idAplicacion: Cardinal);
begin
  inherited Create;
  self.nombreServicio:= nombreServicio;
  self.idAplicacion:= idAplicacion;
end;

procedure TServicioEnEjecucion.dumpToText(var f: TextFile; strIndentacion: String);
begin
  writeln(f, strIndentacion, 'nombreServicio= ', nombreServicio, ', idAplicacion= ', idAplicacion);
end;

//=====================
//Métodos de TFichaNodo
//---------------------

Constructor TFichaNodo.Create(idNodo, idTopo: Cardinal; nombreNodo: String);
begin
  inherited Create;
  if idNodo = 0 then
    self.idNodo:= getIdNodoLocal
  else
    self.idNodo:= idNodo;
  self.idTopo:= idTopo;
  self.nombre:= AnsiLowerCase(nombreNodo);
  listaServicios:= TList.Create;
  self.velocidad:= 1E-8;
  QueryPerformanceCounter(self.dtUltimoPedido);
  self.dtVencimientoGlobal:= MaxInt;
  self.nVecesConsecutivasQueNoRespondio:= 0;
end;

function TFichaNodo.idServicio(nombreServicio: String): Cardinal;
var
  i: Integer;
  nomServAsPChar: PAnsiChar;
  res: Cardinal;
begin
  res:= 0;
  for i:= 0 to listaServicios.Count - 1 do
    if TServicioEnEjecucion(listaServicios[i]).nombreServicio = nombreServicio then
    begin
      res:= TServicioEnEjecucion(listaServicios[i]).idAplicacion;
      break;
    end;
  if res = 0 then
  begin
    GetMem(nomServAsPChar, length(nombreServicio) + 1);
    StrPCopy(nomServAsPChar, nombreServicio);
    res:= getIdAplicacion(idNodo, nomServAsPChar);
    FreeMem(nomServAsPChar, length(nombreServicio) + 1);
    if res <> 0 then
      listaServicios.Add(TServicioEnEjecucion.Create(nombreServicio, res))
  end;
  result:= res;
end;

procedure TFichaNodo.quitarServicio(nombreServicio: String);
var
  i: Integer;
begin
  for i:= 0 to listaServicios.Count - 1 do
    if TServicioEnEjecucion(listaServicios[i]).nombreServicio = nombreServicio then
    begin
      listaServicios.Delete(i);
      break;
    end;
end;

procedure TFichaNodo.dumpToText(var f: TextFile; strIndentacion: String);
var
  i: Integer;
begin
  writeln(f, strIndentacion, 'idNodo= ', idNodo);
  writeln(f, strIndentacion, 'nombre= ', nombre);
  writeln(f, strIndentacion, 'idTopo= ', idTopo);
  writeln(f, strIndentacion, 'velocidad= ', velocidad);
  writeln(f, strIndentacion, 'dtUltimoPedido= ', dtUltimoPedido);
  writeln(f, strIndentacion, 'dtVencimientoGlobal= ', dtVencimientoGlobal);
  Writeln(f, strIndentacion, 'listaServicios:');
  Writeln(f, strIndentacion, 'Count= ', listaServicios.Count);
  for i:= 0 to listaServicios.Count - 1 do
    TServicioEnEjecucion(listaServicios[i]).dumpToText(f, strIndentacion + charIndentacion);
end;

end.
