/**
  * Persiste un clip en tantos servidores como el valor de replica. Cuando la cantidad de
  * servidores provistos es mayor a la cantidad de replicas a realizar, se seleccionan los que
  * tienen menos cantidad de archivos.
  *
  * @param servidores Servidores en los que se puede almacenar el clip.
  * @param replicas Cantidad de replicas a conservar del clip (en cuantos servidores redundantes).
  * @param clipdata El clip a guardar
  * @return
  */
 public static boolean guardarClipEnLosAlgunosDeLosServidores(
     List<StorageServer> servidores, int replicas, ClipData clipdata) {
   boolean pudeGuardarAlMenosUnaCopia = false;
   for (int i = 0; i < replicas; i++) {
     if (servidores.size() > 0) {
       StorageServer mejorServidorParaAlmacenarClip =
           StorageServerLists.getSiguienteServidorParaAlmacenarClip(servidores);
       servidores.remove(mejorServidorParaAlmacenarClip);
       try {
         Storage.getInstance().guardar(mejorServidorParaAlmacenarClip, clipdata);
         ClipDataToServerRelation clipDataServerRelation = new ClipDataToServerRelation();
         clipDataServerRelation.setClipId(clipdata.getClip().getId());
         clipDataServerRelation.setServidor(mejorServidorParaAlmacenarClip);
         StorageMappingManager.addClipDataServerRelation(clipDataServerRelation);
         pudeGuardarAlMenosUnaCopia = true;
       } catch (IOException e) {
         i--;
         StorageServerCommunicationsHelper.recuperar(mejorServidorParaAlmacenarClip);
       }
     } else {
       log.warn("guardarClipEnLosAlgunosDeLosServidores recibió una lista vacía de servidores");
       break;
     }
   }
   return pudeGuardarAlMenosUnaCopia;
 }
 /**
  * Una vez que un servidor se ha caido, se inicia un proceso de recuperación del mismo, en el que
  * se recuperan las copias redundantes perdidas y se procura periódicamente volver a establecer la
  * conexión.
  *
  * @param servidorCaido El servidor que se ha caido.
  */
 public static void recuperar(StorageServer servidorCaido) {
   servidorCaido.setOnline(false);
   List<ClipDataToServerRelation> listaDeClipsARecuperar =
       StorageMappingManager.getAndRemoveAllClipDataServerRelationsOfServer(servidorCaido);
   for (ClipDataToServerRelation unClipARecuperar : listaDeClipsARecuperar) {
     log.debug("Iniciando recuperacion del clip: " + unClipARecuperar.getClipId());
     if (!StorageMappingManager.tengoLaCantidadDeReplicasNecesariasParaElClip(
         unClipARecuperar.getClipId())) {
       log.debug(
           "Recuperacion del clip: " + unClipARecuperar.getClipId() + " se creara una copia");
       ClipData clipData =
           ClipStorageImpl.getInstancia().getClipDataByClipId(unClipARecuperar.getClipId());
       log.debug(
           "Recuperacion del clip: "
               + unClipARecuperar.getClipId()
               + " se leyó el clip de otro servidor");
       List<StorageServer> servidoresDisponiblesSinEsteClip =
           StorageMappingManager.getStorageServersSinClipDataById(unClipARecuperar.getClipId());
       log.debug(
           "Recuperacion del clip: "
               + unClipARecuperar.getClipId()
               + " hay: "
               + servidoresDisponiblesSinEsteClip.size()
               + " servidores disponibles para guardar la copia leída");
       StorageServerCommunicationsHelper.guardarClipEnLosAlgunosDeLosServidores(
           servidoresDisponiblesSinEsteClip, 1, clipData);
       log.debug(
           "Recuperacion del clip: "
               + unClipARecuperar.getClipId()
               + " la copia ha sido guardada");
     }
   }
   servidorCaido.setAmountOfClipDataStored(0);
   while (!servidorCaido.isOnline()) {
     try {
       Thread.sleep(
           Configuration.getIntConfiguration(
               ConfigurationItemsEnum.TIEMPOENTREINTENTOSLEVANTARSERVIDORCAIDO));
       StorageServerCommunicationsHelper.conectarServidor(servidorCaido);
     } catch (InterruptedException e) {
       log.warn(e.getStackTrace());
       log.warn(
           "Ha ocurrido una InterruptedException cuando estaba bloqueado el proceso para recuperar el servidor: "
               + servidorCaido.getAddress()
               + " Se continuará la ejecución.");
     } catch (IOException e) {
       log.warn(e.getStackTrace());
       log.warn("El servidor: " + servidorCaido.getAddress() + " continúa lanzando IOException.");
     }
   }
 }
  /**
   * Intenta conectarse con el servidor de almacenamiento provisto, en caso de que eso funcione
   * correctamente, se crea el mapeo en memoria con los archivos contenidos en el. Si el servidor a
   * conectar tiene copios de un clip en exeso (hay mas copias que las requeridas), ésta se borra
   * para liberar espacio.
   *
   * @param server Servidor al que conectarse.
   * @throws IOException En caso de que la conexión falle.
   */
  public static void conectarServidor(StorageServer server) throws IOException {
    log.debug("Iniciando conexion con: " + server.getAddress());
    String[] fileNames = Storage.getInstance().listarArchivosEnServidor(server);
    for (String unFileName : fileNames) {
      try {
        ClipDataToServerRelation newClipDataServerRelation = new ClipDataToServerRelation();
        newClipDataServerRelation.setServidor(server);
        newClipDataServerRelation.setClipId(Long.parseLong(unFileName));
        if (StorageMappingManager.tengoLaCantidadDeReplicasNecesariasParaElClip(
            newClipDataServerRelation.getClipId())) {
          Storage.getInstance().borrar(server, newClipDataServerRelation.getClipId());
        } else {
          StorageMappingManager.addClipDataServerRelation(newClipDataServerRelation);
          log.debug(
              "ClipData: Id="
                  + newClipDataServerRelation.getClipId()
                  + " Servidor="
                  + newClipDataServerRelation.getServidor().getAddress());
        }

      } catch (NumberFormatException e) {
        log.warn(
            "Hay un archivo con nombre corrupto: "
                + unFileName
                + " en el servidor: "
                + server.getAddress());
      }
    }
    server.setAmountOfClipDataStored(fileNames.length);
    server.setOnline(true);
  }