///////////////////////////////////////////////////////////////////////////////
///
//          STFSd_read
///
/// \brief  Reads from an STFS file
///
///////////////////////////////////////////////////////////////////////////////
ssize_t
STFSd_read(STFS_OpenIdentifier *pp_OpenId,
           void                *pp_Buf,
           size_t               pv_Count)
{
  const char     *WHERE = "STFSd_read";
  STFS_ScopeTrace lv_st(WHERE);
  STFS_Session *lp_Session = STFS_Session::GetSession();

  if(!lp_Session) {
    return -1;
  }

  if(!pp_OpenId || !pp_Buf) {
    //Invalid argument errno
    return -1;
  }

  if (pv_Count > (size_t)STFS_SSIZE_MAX) {
    return -1;
  }

  //If count is > buffer size then what? Handle this at the send.cpp level

  //Lookup Open file,  Need to have added check to see if node matches
  STFS_ExternalFileOpenerContainer *lp_EfoContainer = STFS_ExternalFileOpenerContainer::GetInstance();
  if (!lp_EfoContainer) {
    TRACE_PRINTF2(1,"%s\n", "Null EFO Container");
    return -1;
  }

  STFS_ExternalFileOpenerInfo *lp_Efoi = lp_EfoContainer->Get(pp_OpenId);
  if (!lp_Efoi) {
    TRACE_PRINTF3(1,
                  "Open Id: %d,%ld not found in the EFO Container\n",
                  pp_OpenId->sqOwningDaemonNodeId,
                  pp_OpenId->openIdentifier
                  );
    return -1;
  }
  STFS_ExternalFileMetadata *lp_Efm = lp_Efoi->efm_;
  if (!lp_Efm) {
    TRACE_PRINTF1(1,"Null EFM Found in the lp_Efoi Entry\n");
    return -1;
  }

  TraceOpeners(lp_EfoContainer,
               lp_Efm);
  

  //Check to see if the file is local

  //If not local then Don't do anything. Return 0.

  //Do Read


  return 0;
}
///////////////////////////////////////////////////////////////////////////////
///
//          STFSd_close
///
/// \brief  Processes a file close request given the open identifier
///
/// \param  STFS_OpenIdentifier *pp_OpenId
/// 
///////////////////////////////////////////////////////////////////////////////
int
STFSd_close(STFS_OpenIdentifier *pp_OpenId)
{
  const char     *WHERE = "STFSd_close";
  STFS_ScopeTrace lv_st(WHERE);

  if (!pp_OpenId) {
    return -1;
  }

  STFS_ExternalFileOpenerContainer *lp_EfoContainer = STFS_ExternalFileOpenerContainer::GetInstance();
  if (!lp_EfoContainer) {
    TRACE_PRINTF2(1,"%s\n", "Null EFO Container");
    return -1;
  }

  STFS_ExternalFileOpenerInfo *lp_Efoi = lp_EfoContainer->Get(pp_OpenId);
  if (!lp_Efoi) {
    TRACE_PRINTF3(1,
                  "Open Id: %d,%ld not found in the EFO Container\n",
                  pp_OpenId->sqOwningDaemonNodeId,
                  pp_OpenId->openIdentifier
                  );
    return -1;
  }
  STFS_ExternalFileMetadata *lp_Efm = lp_Efoi->efm_;
  if (!lp_Efm) {
    TRACE_PRINTF1(1,"Null EFM Found in the Efoi Entry\n");
    return -1;
  }

  TraceOpeners(lp_EfoContainer,
               lp_Efm);
  
  int lv_Ret = lp_Efm->Close(true);
  if (lv_Ret < 0) {
    return lv_Ret;
  }

  lv_Ret = lp_EfoContainer->Delete(pp_OpenId);
  if (lv_Ret < 0) {
    return lv_Ret;
  }

  TraceOpeners(lp_EfoContainer,
               lp_Efm);

  lv_Ret = STFS_ExternalFileMetadata::DeleteFromContainer(lp_Efm);
  if (lv_Ret < 0) {
    return lv_Ret;
  }

  return lv_Ret;
}
///////////////////////////////////////////////////////////////////////////////
///
//          STFSd_createFragment
///
/// \brief  Creates a file fragment
///         - Figures out the node of the file fragment 
///            (Currently it is the current node. TBD - check for the node)
///         - Creates a directory
///         - Creates a file in the created directory 
///         - opens the file (controlling open)
///
/// \param STFS_ExternalFileMetadata  *pp_Efm
/// \param int                         pv_OpenerNodeId,
/// \param int                         pv_OpenerPID,
/// \param long                        pv_FragmentFileOffset
/// 
///////////////////////////////////////////////////////////////////////////////
int
STFSd_createFragment(STFS_ExternalFileMetadata  *pp_Efm,
                     int                         pv_OpenerNodeId,
                     int                         pv_OpenerPID,
                     long                        pv_FragmentFileOffset)
{
  const char     *WHERE = "STFSd_createFragment";
  STFS_ScopeTrace lv_st(WHERE);

  /// housekeeping
  int lv_Ret = 0;

  if (!pp_Efm) {
    return -1;
  }

  TRACE_PRINTF5(2,
                "FileName: %s, Opener NodeId: %d, Opener SQ PID: %d, FragmentFileOffset: %ld\n",
                pp_Efm->ExternalFileNameGet(),
                pv_OpenerNodeId,
                pv_OpenerPID,
                pv_FragmentFileOffset);

  /// loop over all possible storage locations
  bool lv_moreStorageLocations = false;
  bool lv_fragmentCreated = false;

  while ((lv_moreStorageLocations != true) && (lv_fragmentCreated == false) ) {


    /// pick a storage location if one is available

    char lp_StorageLocationDir[STFS_PATH_MAX];
    bool lv_stgIsLocal = false;

    lv_Ret = STFS_fragment::GetStorageLocation (lp_StorageLocationDir,
                                                &lv_stgIsLocal);

    if (lv_Ret < 0) {
      lv_moreStorageLocations = false;         
    }

    else {

      if (lv_stgIsLocal == true){

        /// Local storage location:  Create the fragment!

        char lv_DirName[STFS_DIRNAME_MAX+1];

        bool lv_MountPointExists
                    = STFS_util::GetMountPointName(lv_DirName, 
                                                lp_StorageLocationDir); 
        ASSERT (lv_MountPointExists == true);


        /// Set up the filename
        char fragmentFilename[STFS_DIRNAME_MAX+STFS_NAME_MAX];
        STFS_fs *lp_Fs = new STFS_ext2();
        if (!lp_Fs) {
          TRACE_PRINTF1(1, "Unable to construct STFS_ext2\n");
          return -1;
        }

        size_t lv_NumFragments = pp_Efm->GetNumFragments();
        sprintf(fragmentFilename, "%s%s/f%d_", 
                lv_DirName, 
                pp_Efm->ExternalFileNameGet(),
                (short) lv_NumFragments);


        ///  Issue the mkstemp

        long lv_fsErr = lp_Fs->mkstemp(fragmentFilename);
        if (lv_fsErr < 0) {
          TRACE_PRINTF1 (1, "createFragment:FS_mkstemp is unable to create a tempfile\n");
          return lv_fsErr;
        }

        ///  Init/link the FFM  
        lv_fsErr = STFS_fragment::InitFrag (pp_Efm,
                                            lp_Fs->FilenameGet(),
                                            lp_StorageLocationDir,
                                            pv_FragmentFileOffset);
        if (lv_fsErr<0) {
          //TBD cleanup
          return -1;
        }


        /// Get the EFH for the controlling open  

        // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
        //
        // This code doesn't work for remote fragments, remote accessors of
        // local fragments, or local accessors of remote files with remote
        // fragments!  They'll need their own EFHs and this doesn't link this
        // fragment to them.  Further, the check to determin whether we're
        // creating the controlling open doesn't work if there are multiple
        // fragments but this is the first fragment on this node.
        //
        // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING



        // Get the efh for the controlling open
        STFS_ExternalFileHandle *lp_Efh = NULL;
        if ( (pp_Efm->GetNumFragments()) == 1) {
          // create the controlling open

          lp_Efh= pp_Efm->Open(true);
        }
        else {
          // get the controling open from the efm

          lp_Efh = pp_Efm->EFHGet();
        }

        if (!lp_Efh) {
          // TBD cleanup
          return -1;
        }

        /// Logically open the fragment

        lv_fsErr = STFS_fragment::Open (lp_Efh, (pp_Efm->GetNumFragments()-1), lp_Fs);

        if (lv_fsErr<0) {
          //TBD cleanup
          return -1;
        }

        lv_fragmentCreated = true;

      } // if local fragment
      else {

        /// remote fragment:  Send the request to the remote daemon
        // TBD!
        ASSERT (false);
        return -1;
      }
    }
  } // while more possible places to create frag and frag not created
  
  return lv_Ret;
}