/**
  * Lleva a cabo las acciones pertinentes para que un trabajo se declare como vivo.<br>
  * (Por ahora es solamente escribir en la base de datos el estado que tiene que ver con
  * cont_externo.)
  */
 private void recibeSigueVivo() {
   try {
     this.subtraV.write();
     info.getConex().dbCommit();
   } catch (ADMINGLOExcepcion e) {
     e.printStackTrace();
   } catch (OIExcepcion e) {
     e.printStackTrace();
   }
 }
  /**
   * Lleva a cabo preparaciones para ejecutar el método del sirviente en el método ejecutar(),
   * además de hacer la recepción de eventuales resultados de subtrabajos.
   *
   * @return Si se puede dar inicio a la ejecución. De lo contrario ésta (la ejecución del método
   *     invocado) no se realiza y se llamada en cambio a ejecutarFin con parámetros null y false.
   * @throws ADMINExcepcion Si hay error.<br>
   *     <b>Estado de los archivos (fisico y el lógico que les corresponde)</b>
   *     <pre>
   * +--------------------+--------------------+
   * | Estado físico      | Estado lógico*     |
   * +--------------------+--------------------+
   * | ausente            | ausente            |
   * | partido            | importando         |
   * | unido y comprimido | presente           |
   * | descomprimido      | listo              |
   * +--------------------+--------------------+
   * __________________________________
   * *El estado lógico se da al verificar el estado físico
   * de los archivos y es registrado en la base de datos con
   * el fin de no hacer verificaciones físicas.
   * </pre>
   *     <li>Si un archivo está listo, no se modifica.
   *     <li>Si un archivo está presente, se descomprime y se pone listo
   *     <li>Si un archivo no está en uno de los estados anteriores, entonces se borra y se impone
   *         el contenido importado. <b>Estado del solicitante<b>
   *         <pre>
   * +------------------------+---------------------------------------------+
   * | Estado                 | Situación                                   |
   * +------------------------+---------------------------------------------+
   * | SOLICITANTE_INICIO     | El solicitante está recién iniciado         |
   * |                        |                                             |
   * | SOLICITANTE_PREPTAREA  | El solicitante tiene una tarea registrada   |
   * |                        |                                             |
   * | SOLICITANTE_YATAREA    | El solicitante importó sus archivos         |
   * |                        |                                             |
   * | SOLICITANTE_LISTO      | El solicitante descomprimió sus archivos    |
   * |                        |                                             |
   * | SOLICITANTE_INVALIDO   | El solicitante, su tarea y sus archivos     |
   * |                        | tuvieron problemas al ser establecidos      |
   * |                        | para tdderive.                              |
   * +------------------------+---------------------------------------------+
   * </pre>
   */
  public boolean ejecutarInicio() throws ADMINGLOExcepcion {
    ADMINPOLPlanificador planificador = null;
    ADMINAPPControladores controlador = null;
    boolean bSiIniciado = false;
    int caso = 0;
    /*
     * Esto para que la instancia de la tarea y del subtrabajo sean los mismos
     * respetar el estado de la tarea que ya tiene el servidor, pues el open se lo come
     */
    // tarea.setEstadoTarea(ADMINAPPITareas.TAREA_MARCHA); // ya no
    if (this.siSubtrabajo()) {
      /*
       * para subtrabajos URGE hacer el controlador, si se espera hay problemas de
       * concurrencia y más de un hilo querrá hacer su controlador
       */
      planificador = info.getPlanificador();
      synchronized (planificador.objeto_bloqueo_decidiendo) {
        controlador = planificador.nuevoControlador(new ADMINAPPTrabajos(tarea, solicitante));
      }
      this.tareaV = this.tarea;
      this.subtraV = this.subtrabajo;
      //      controlador=this.info.getPlanificador().cargaControlador(this.tarea.getIdTarea());
      //      if(controlador!=null){
      synchronized (controlador) {
        tareaV = controlador.getTarea();
        if (tareaV != null) {
          this.subtraV = controlador.getSubtrabajo(this.subtrabajo.getIdSubtrabajo());
          if (subtraV == null) {
            this.subtraV = this.subtrabajo;
            controlador._tarea.addSubtrabajo(this.subtraV);
          }
        }
      }
      //      }else{
      //      }
    }
    /*
     * pone estados al solicitante y a la tarea
     * <2005/> y al subtrabajo
     * [ ] Debe revisarse si la tarea o el subtrabajo ya están presentes.
     * [ ] Si existen el solicitante de la tarea siempre va a ser nuevo (importante
     *     para análisis de tiempos).
     */
    /*
     * <2006/> Toqueteo para considerar los keepalive.
     */
    caso = this.revisaConsistencia();
    if (caso == 0) {
      // mejor aquí no porque la tarea aún no tiene id
      // info.println("despachador","recibe solicitud tarea: " + tarea.getIdTarea());
    }
    if (caso == 2 && (!this.siSubtrabajo())) {
      // la tarea ya estaba solicitada
      return true;
    }
    /*
     * en todo caso, debe saberse si el subtrabajo es importado
     * para ponerle el controlador remoto que le corresponde (el
     * nombre del nodo actual)
     */
    if (this.siSubtrabajo() && !subtraV.siLocal()) {
      // debe escribirse el nombre del servidor actual
      subtraV.setContRemoto(this.info.getComputadora().getNombre());
    }
    if (this.siSubtraSolicitud() && this.subtrabajo.hashCode() != this.subtraV.hashCode()) {
      // el subtrabajo se repite
      if (this.subtraV.getEstadoSubtrabajo().compareTo(ADMINAPPISub_trabajos.SUBTRA_EXTERNO) == 0) {
        // para que los muertos no revivan
        this.subtraV.setEstadoSubtrabajo(ADMINAPPISub_trabajos.SUBTRA_ESPERA);
      }
      // this.tareaV.loadPrograma();
      this.subtraV.write();
      try {
        info.getConex().dbCommit();
      } catch (OIExcepcion e1) {
        e1.printStackTrace();
      }
      /*
       * debe indicarse al solicitante que ya tiene los datos
       * y que no hace falta que se los exporte
       */
      info.println(
          "despachador",
          "recibe subtrabajo a planificarr: "
              + tareaV.getIdTarea()
              + ":"
              + subtraV.getIdSubtrabajo());
      try {
        this.omiteImportacion();
      } catch (ADMINGLOExcepcion e2) {
        e2.printStackTrace();
      } catch (OIExcepcion e2) {
        e2.printStackTrace();
      }
      return true;
    }
    if (caso == 3) {
      // la tarea y el subtrabajo ya estaban listos
      // debe revisarse si se está devolviendo el resultado
      // de un subtrabajo...
      // o si estamos ante un keepalive.
      if (this.siSubtrabajoFin()) {
        // YUPI!!!!
        recibeResultado();
        info.println(
            "despachador",
            "recibe subtrabajo terminado: "
                + tareaV.getIdTarea()
                + ":"
                + subtraV.getIdSubtrabajo());
        try {
          info.recibeMensajeDeNodo(this.getHostRemoto());
        } catch (OACTExcepcion e1) {
          e1.printStackTrace();
        }
        return true;
      }
      if (subtraV.siLocal() && this.siSigueVivo()) {
        recibeSigueVivo();
        info.println(
            "despachador",
            "recibe subtrabajo sigue vivo: "
                + tareaV.getIdTarea()
                + ":"
                + subtraV.getIdSubtrabajo());
        try {
          info.recibeMensajeDeNodo(this.getHostRemoto());
        } catch (OACTExcepcion e1) {
          e1.printStackTrace();
        }
        return true;
      }
    }
    if (this.siSubtrabajo()) {
      info.println(
          "despachador",
          "recibe subtrabajo a planificar: "
              + tareaV.getIdTarea()
              + ":"
              + subtraV.getIdSubtrabajo());
      try {
        info.recibeMensajeDeNodo(this.getHostRemoto());
      } catch (OACTExcepcion e1) {
        e1.printStackTrace();
      }
    }
    try {
      // el solicitante siempre es nuevo
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_INICIO);
      solicitante.setTarea(tarea);
      solicitante.write();
      if (caso == 0 && !this.siSubtrabajo()) {
        info.println(
            "despachador",
            "recibe solicitud tarea: (" + tarea.getAlias() + ") " + tarea.getIdTarea());
      }
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_PREPTAREA);
      solicitante.setDesdeNombre(this.getHostRemoto());
      solicitante.setDesdePuerto(this.getPuertoRemoto());
      tarea.createDirs();
      tarea.loadPrograma();
      if (caso == 2) {
        /*
         * tarea presente mientras se solicita un subtrabajo ausente
         * califica al solicitante
         */
        solicitante.setTipoSol(ADMINAPPISolicitantes.SOLICITANTE_TIPOSUBTRABAJO);
      }
      solicitante.write();

      // <2005 Revisa si es un subtrabajo/>
      if (this.siSubtrabajo()) {
        tareaV.setEstadoTarea(ADMINAPPITareas.TAREA_PREPARACION);
        subtraV.setEstadoSubtrabajo(ADMINAPPISub_trabajos.SUBTRA_INICIO);
        /*
         * es un subtrabajo cuyo ambiente debe ser
         * configurado por mientras la tarea ya está lista.
         */
        tareaV.write();
        /*
         * ojo: el directorio del subtrabajo se debe acoplar
         * siempre a la configuración local del
         * agente de tdderive, es por eso que tal dirección
         * no viene predeterminada para el subtrabajo en
         * la solicitud html.
         */
        subtraV.setDirectorio(tareaV.getTareaDir() + "/" + subtraV.getIdSubtrabajo());
        subtraV.createDirs();
        // importa archivos para el subtrabajo
        if (this.importaArchivos()) {
          subtraV.setEstadoSubtrabajo(ADMINAPPISub_trabajos.SUBTRA_ESPERA);
          /*
           * hace la asociación entre el subtrabajo y
           * sus archivos
           */
          subtraV.setArchivos(this.mpArchivos);
        }
        /*
         * se asegurar la persistencia de la relación
         * entre el subtrabajo y sus archivos.
         */
        subtraV.write();
        tareaV.setEstadoTarea(ADMINAPPITareas.TAREA_MARCHA);
      } else {
        // no es subtrabajo
        /*
         * la tarea se pide por primera vez, es la coordinadora,
         * quien la da a conocer al resto del sistema.
         * De este hecho solamente hay certeza en este punto
         */
        tarea.setEstadoTarea(ADMINAPPITareas.TAREA_INICIO);
        this.tarea.setSiCoordina(true);
        if (!_si_local) {
          // todos los archivos deben importarse
          this.importaArchivos();
        } else {
          // todos los archivos son locales
          this.ubicaArchivos();
        }
        tarea.setArchivos(this.mpArchivos);
        tarea.write();
      }
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_YATAREA);
      solicitante.write();
      descompArchivos();
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_LISTO);
      /*             |
       *             |
       *             V
       * realiza chequeos de instancias concretas de LEESolicitudAbs
       */
      revisaEstados();
      /*
       * el grupo de la solicitud debe ser el mismo código de la tarea.
       */
      solicitante.setIdGrupo(tarea.getIdTarea());
      solicitante.setRetornos(this.mpRetornos);
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_LISTO);
      solicitante.write();
      if (tareaV != null) {
        tareaV.write();
      } else {
        tarea.write();
      }
      // @FIXME escribir los retornos en la base de datos
      // @TODO Commit que debería ser el primero.
      info.getConex().dbCommit();
      bSiIniciado = true;
    } catch (ADMINGLOExcepcion ex) {
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_INVALIDO);
      bSiIniciado = false;
    } catch (OIExcepcion ex) {
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_INVALIDO);
      bSiIniciado = false;
    } catch (OACTExcepcion ex) {
      solicitante.setEstadoSolicitante(ADMINAPPISolicitantes.SOLICITANTE_INVALIDO);
      bSiIniciado = false;
    }
    try {
      solicitante.write();
    } catch (OIExcepcion e) {
      // ni modo, no se pudo hacer persistente el estado
    }
    return bSiIniciado;
  }