/**
   * Perform a given file operation based on the operationId, which will be used to retrieve the
   * operation details from the CurrentOperations class
   */
  public void requestFileOperation(Long operationId) throws Exception {
    Operation operation = CurrentOperations.getOperation(operationId);

    switch (operation.getOperationType()) {
      case OperationType.FILE_OP_LS:
        ls(operation);
        break;
      case OperationType.FILE_OP_WRITE:
        writeFile(operation);
        break;
      case OperationType.FILE_OP_READ:
        readFile(operation);
        break;
    }
  }
  private void writeFile(Operation operation) throws Exception {
    Logger.logDebug("Start operation to send writeFile request to datanode", getClass());
    // on a write request, the parameter is a FileWriteOperationParameter
    FileWriteOperationParameter fileWriteParm =
        (FileWriteOperationParameter) operation.getParamProto();

    // find all datanodes that will be receiving that file
    List<DatanodeInfo> datanodes = Datanodes.findDatanodesForFileWrite(fileWriteParm.getDfsFile());
    Logger.logDebug(
        "Operation will send write request to " + datanodes.size() + " datanodes: ", getClass());
    // add the chosen datanodes to the operation parameter
    for (DatanodeInfo datanodeInfo : datanodes) {
      fileWriteParm.addDatanode(datanodeInfo);
      Logger.logDebug(">>> " + datanodeInfo, getClass());
    }

    // remove valid datanodes from the dfsFile
    FileStructure.getInstance()
        .removeValidDatanodes(fileWriteParm.getFilePath(), fileWriteParm.getDfsFile().getName());

    // send the request to the first datanode
    FileOperationReqProtocol fileOperationRequest =
        new FileOperationReqProtocolImpl(fileWriteParm.findNextDatanode(), operation);
    fileOperationRequest.requestFileOperation();
  }
  /** *********** OLD STUFF ********** */
  @Deprecated
  private void ls(Operation operation) throws Exception {
    // on an ls request, the parameter is a FilePathProto
    FilePathProto path = (FilePathProto) operation.getParamProto();

    // get the possible datanodes ids we can ls from
    FileStructureOperation fileStructureOperation = new FileStructureOperationImpl();
    List<String> validDatanodesIds = fileStructureOperation.ls(path.getPath());

    // figure the preferred datanode
    // DatanodeInfo datanode = Datanodes.findPreferredDatanode(validDatanodesIds);
    // DatanodeInfo datanode = Datanodes.findPreferredDatanode(null);
    DatanodeInfo datanode = new DatanodeInfo("datanode1", "127.0.0.1", 30000);

    // send the request to the datanode
    FileOperationReqProtocol fileOperationRequest =
        new FileOperationReqProtocolImpl(datanode, operation);
    fileOperationRequest.requestFileOperation();
  }
  private void readFile(Operation operation) throws Exception {
    Logger.logDebug("Start operation to send readFile request to datanode", getClass());
    // on a read request, the parameter is a FileReadOperationParameter
    FileReadOperationParameter fileReadParm =
        (FileReadOperationParameter) operation.getParamProto();

    // find the datanode that will be sending that file
    List<DatanodeInfo> datanodes = Datanodes.findDatanodesForFileWrite(fileReadParm.getDfsFile());
    Logger.logDebug("Operation will send read request to one of the valid datanodes: ", getClass());
    // add the chosen datanodes to the operation parameter
    for (DatanodeInfo datanodeInfo : datanodes) {
      fileReadParm.addDatanode(datanodeInfo);
      Logger.logDebug(">>> " + datanodeInfo, getClass());
    }

    // TODO receive file from multiple datanodes, someday

    // send the request to the first datanode
    FileOperationReqProtocol fileOperationRequest =
        new FileOperationReqProtocolImpl(fileReadParm.findNextDatanode(), operation);
    fileOperationRequest.requestFileOperation();
  }