/// \brief Delete a name and possibly the file that it refers to int STFSLIB_unlink (const char *pp_Path) { const char *WHERE = "STFSLIB_unlink"; STFS_ScopeTrace lv_st(WHERE); int lv_Ret = 0; //Check that the pathname passed is not longer than our MAX ASSERT(strlen(pp_Path) <= STFS_PATH_MAX); STFS_ExternalFileMetadata *lp_Efm = STFS_ExternalFileMetadata::GetFromContainer((char *) pp_Path); if (lp_Efm) { lp_Efm->Unlink(); if (lv_Ret < 0) { return -1; } } #ifdef SQ_PACK lv_Ret = SendToSTFSd_unlink((char *) pp_Path, STFS_util::GetMyNodeId(), STFS_util::GetMyPID()); #else lv_Ret = STFSd_unlink((char *) pp_Path); #endif return lv_Ret; }
bool LibRead_GetMoreFragments (STFS_ExternalFileHandle *pp_Efh) { const char *WHERE = "LibRead_GetMoreFragments "; STFS_ScopeTrace lv_st(WHERE,2); ///////////////////////////// /// Check Parameters //////////////////////////// if (pp_Efh == NULL) { ASSERT (false); return false; } //Will the order of the ffh's match in the vector between daemon and lib? //How can we tell which one to put... Can add logic to compare //int lv_Ret = 0; //For now just work on grabbing the efm from the daemon ///////////////////////////// /// Setup and Housekeeping ///////////////////////////// bool lv_newFragmentsFound = false; ///////////////////////////// /// Finis! ///////////////////////////// return lv_newFragmentsFound; }
/////////////////////////////////////////////////////////////////////////////// /// // 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; }
/////////////////////////////////////////////////////////////////////////////// /// // STSFSLIB_error() /// /// \brief The actual implementation of an STFS_write /// /// This method is the driver for an STFS_write() function call. /// it also implements the protocol for determining whether or not /// to create a new fragment. Only STFSLIB can make this call, not /// STFS-d, so the logic is put here. We could put a lot of "if /// !ExecutingInDaemon" escape clauses, but there's no need to put /// those in the mainline remote write path. /// /// /// \param pv_Offset byte offset count based on whence /// \param pv_Whence values are as follow: \n /// SEEK_SET - The offset is set to offset bytes. \n /// SEEK_CUR - The offset is set to its current /// location plus offset bytes. \n /// SEEK_END - The offset is set to the size of the /// file plus offset bytes. /// /// \retval off_t SUCCESS: The resulting offset location from beginning /// of current fragment file.\n /// FAILURE: -1 /// /////////////////////////////////////////////////////////////////////////////// int STFSLIB_error ( stfs_fhndl_t pv_Fhandle, int *pp_error, int *pp_addlError, char *pp_context, size_t pv_contextMaxLen, size_t *pp_contextLen ) { const char *WHERE = "STFSLIB_error"; STFS_ScopeTrace lv_st(WHERE); ////////////////////////////////// /// Validate parameters ////////////////////////////////// if (pv_Fhandle == 0 || pv_Fhandle == -1 ) { // Can't rollerskate without wheels, can't get the error without a handle... return -1; } if (pv_contextMaxLen > 0 && pp_context == NULL) { // said the buffer had a non-zero length, but didn't pass it return -1; } if (pp_context != NULL && pp_contextLen == NULL) { // we need to tell you how long the buffer is... return -1; } ////////////////////////////////// /// Get efh ////////////////////////////////// STFS_ExternalFileHandle *lp_Efh = STFS_ExternalFileHandle::GetExternalFileHandle(pv_Fhandle); ////////////////////////////////// /// Extract error from efh ////////////////////////////////// bool lv_RetBool = lp_Efh->GetError ( pp_error, pp_addlError, pp_context, pv_contextMaxLen, pp_contextLen); if (lv_RetBool == false) { // no more errors found return -1; } return 0; }
/////////////////////////////////////////////////////////////////////////////// /// // STFSd_stat /// /// \brief Processes a stat request /// /// \param stfs_nodeid_t pv_Nid /// \param char *pp_Path /// \param Stfs_StatSet *pp_StatSet /// \param stfs_statmask_t pv_Mask /// /////////////////////////////////////////////////////////////////////////////// int STFSd_stat (stfs_nodeid_t pv_Nid, char *pp_Path, struct STFS_StatSet *pp_StatSet, stfs_statmask_t pv_Mask) { const char *WHERE = "STFSd_stat"; STFS_ScopeTrace lv_st(WHERE,2); int lv_Count = 0; int lv_OpenRet = 0; long *lp_PrevIndex = new long(0); while((lv_Count < STFS_MAX_OPENERS) && (lv_OpenRet == 0)) { strcpy(pp_StatSet->Path[*lp_PrevIndex], pp_Path); lv_OpenRet = STFS_util::STFS_stat(pv_Nid, pp_StatSet->Path[*lp_PrevIndex], lp_PrevIndex, pv_Mask, &pp_StatSet->Stat[*lp_PrevIndex]); if(lv_OpenRet < 0) { //TODO: Error Checking return -1; } if(lv_OpenRet != 1) { lv_Count++; } } TRACE_PRINTF2(4,"Number of files found by STFS_stat: %d\n", lv_Count); pp_StatSet->Count = lv_Count; return 0; }
ssize_t STFSLIB_lseek( stfs_fhndl_t pv_Fhandle, off_t pv_Offset, int pv_Whence) { const char *WHERE = "STFSLIB_lseek"; STFS_ScopeTrace lv_st(WHERE); STFS_ExternalFileHandle *lp_Efh = STFS_ExternalFileHandle::GetExternalFileHandle(pv_Fhandle); if (! lp_Efh) { TRACE_PRINTF2(1, "Error in obtaining External File Handle for %ld\n", pv_Fhandle); return -1; } lp_Efh->ResetErrors(); ssize_t lv_Stat = lp_Efh->Lseek(pv_Offset, pv_Whence); if (lv_Stat < 0) { return -1; } return lv_Stat; }
/////////////////////////////////////////////////////////////////////////////// /// // STSFSLIB_write() /// /// \brief The actual implementation of an STFS_write /// /// This method is the driver for an STFS_write() function call. /// it also implements the protocol for determining whether or not /// to create a new fragment. Only STFSLIB can make this call, not /// STFS-d, so the logic is put here. We could put a lot of "if /// !ExecutingInDaemon" escape clauses, but there's no need to put /// those in the mainline remote write path. /// /// /// \param pv_Offset byte offset count based on whence /// \param pv_Whence values are as follow: \n /// SEEK_SET - The offset is set to offset bytes. \n /// SEEK_CUR - The offset is set to its current /// location plus offset bytes. \n /// SEEK_END - The offset is set to the size of the /// file plus offset bytes. /// /// \retval off_t SUCCESS: The resulting offset location from beginning /// of current fragment file.\n /// FAILURE: -1 /// /////////////////////////////////////////////////////////////////////////////// ssize_t STFSLIB_write( stfs_fhndl_t pv_Fhandle, const void *pp_Buf, size_t pv_Count) { const char *WHERE = "STFSLIB_write"; STFS_ScopeTrace lv_st(WHERE); if (!pp_Buf) { errno = EINVAL; return -1; } STFS_ExternalFileHandle *lp_Efh = STFS_ExternalFileHandle::GetExternalFileHandle(pv_Fhandle); if (! lp_Efh) { TRACE_PRINTF2(1, "Error in obtaining External File Handle for %ld\n", pv_Fhandle); return -1; } lp_Efh->ResetErrors(); bool lv_WriteCompleted = false; ssize_t lv_totalCountWritten = 0; void *lp_currBuffPtr = (void *) pp_Buf; ssize_t lv_writeSize = pv_Count; while (!lv_WriteCompleted) { lp_Efh->SetCurrentFragmentBasedOnCurrOffset(); ssize_t lv_Stat = lp_Efh->Write( lp_currBuffPtr, lv_writeSize); if (lv_Stat == lv_writeSize) { // The usual case: we wrote everything as expected. Prepare // to exit the loop and go home for the day! lv_totalCountWritten += lv_writeSize; lv_WriteCompleted = true; } else if (lv_Stat < 0) { // Hmm, do we need to create a new fragment? if (errno == ENOSPC) { //gotcha! Create a new fragment and continue writing the //buffer STFS_ExternalFileMetadata *lp_EFM = lp_Efh->EfmGet(); // make sure that the lib has the same opinion as the // daemon on the new fragment's offset size_t lv_newFragExpectedOffset = lp_Efh->CurrentOffsetGet(); #ifdef SQ_PACK STFS_OpenIdentifier lp_openIdentifier = lp_Efh->OpenIdentifierGet(); lv_Stat = SendToSTFSd_createFrag(lp_EFM, STFS_util::GetMyNodeId(), STFS_util::GetMyPID(), &lp_openIdentifier); #else lv_Stat = STFSd_createFragment(lp_EFM, STFS_util::GetMyNodeId(), STFS_util::GetMyPID(), lp_Efh->CurrentOffsetGet()); #endif if (lv_Stat < 0) { // Fragment not created. Treat it like a normal ENOSPC // error after all. If the error on the createFrag was // something else, then we'll hope that it was put in // the open error structure... errno = ENOSPC; } else { // open the new fragment lv_Stat = lp_Efh->OpenNewFragments(); if (lv_Stat < 0) { errno=ENOSPC; } // Now check to see if the new fragment has the correct // starting offset. The new fragment isn't yet the // current one, so we have to extract the current number // of fragments, use it as the index to get the last // fragment's FFM, and call OffsetGet on that fragment. size_t lv_newFragRealStartOffset = lp_Efh->GetLastFFMStartOffset(); if (lv_newFragRealStartOffset != lv_newFragExpectedOffset) { // Something's wrong because the daemon has a // different opinion on the previous fragment's // size or our calculations are out of sync. This // is a data integrity problem // This code should really be fixed to change the // if condition to be a Permassert or the // following Assert (false) to kill the library // process. STFS_util::SoftwareFailureHandler (WHERE); } } } if (lv_Stat < 0) { // we've got a real, live error here! // before we just return this error, check to see if we've // written anything! If so, we want to return that // value. It's up to the library caller to decide whether // to retry the I/O in that case. if (lv_totalCountWritten > 0) { return lv_totalCountWritten; } else { // a real error! Make sure errno wasn't overwritten by // this point! Any additional information or subsequent // errors should be stuffed in the error structure by // lower calls. return -1; } } // Not ENOSPC check } // lv_Stat < 0 check else { //Rev. Following line is comparing signed vs unsigned. ASSERT ((size_t)(lv_totalCountWritten+lv_Stat) < pv_Count); // partial write! Hmmmmm, might mean we need a new fragment // (or it might mean there was partial write). We need to // save the number of bytes we wrote and then try again to // write the data. We also have to save our current // location in the buffer and calculate the new number of // bytes to write. // Careful here: it's possible that a single large write // might create more than one fragment! Make sure that // whatever code gets added uses lv_CountWritten and lv_Stat // with the proper context. lv_totalCountWritten += lv_Stat; lp_currBuffPtr = (char *)lp_currBuffPtr + lv_Stat; lv_writeSize -= lv_Stat; } } // While !lv_WriteCompleted return lv_totalCountWritten; }
/////////////////////////////////////////////////////////////////////////////// /// // STFSd_open /// /// \brief Opens an existing STFS file /// /// \param const char *pp_Path, /// \param int pv_OFlag, /// \param pv_OpenerNodeId, /// \param pv_OpenerPID, /// \param STFS_ExternalFileMetadata *&pp_Efm, /// \param STFS_FragmentFileMetadata *&pp_Ffm, /// \param STFS_OpenIdentifier *&pp_OpenId) /// /////////////////////////////////////////////////////////////////////////////// int STFSd_open(const char *pp_Path, int pv_OFlag, int pv_OpenerNodeId, int pv_OpenerPID, STFS_ExternalFileMetadata *&pp_Efm, STFS_FragmentFileMetadata *&pp_Ffm, STFS_OpenIdentifier *&pp_OpenId) { const char *WHERE = "STFSd_open"; STFS_ScopeTrace lv_st(WHERE); STFS_Session *lp_Session = STFS_Session::GetSession(); int lv_Ret = 0; if (!pp_Path) { errno = EINVAL; char lp_ErrMess[] = "Error Path is NULL"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -1; } char lp_Path[STFS_PATH_MAX]; strcpy(lp_Path, pp_Path); STFS_ExternalFileMetadata *lp_Efm = STFS_ExternalFileMetadata::GetFromContainer(lp_Path); if(!lp_Efm) { TRACE_PRINTF2(1,"%s\n", "Error getting lp_Efm"); errno = EINVAL; char lp_ErrMess[] = "Error getting lp_Efm"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -2; } TRACE_PRINTF4(2, "FileName: %s, Opener Node Id: %d, Opener SQ PID: %d\n", lp_Efm->ExternalFileNameGet(), pv_OpenerNodeId, pv_OpenerPID); STFS_util::ValidateEFM(lp_Efm); if(!lp_Efm->FileAvailableGet()) { TRACE_PRINTF2(1, "File: %s is no longer available\n", pp_Path); errno = ENOENT; char lp_ErrMess[] = "Error file is no longer available"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -1; } int lv_FragmentOffset = 0; //If O_APPEND, last fragment will be set open, if((pv_OFlag & O_APPEND) == O_APPEND) { lv_FragmentOffset = lp_Efm->GetNumFragments(); if(lv_FragmentOffset == 0) { TRACE_PRINTF2(1,"%s\n", "Error Number of Fragments returned is 0"); errno = ENOENT; char lp_ErrMess[] = "Error number of fragments returned is 0"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -3; } lv_FragmentOffset -= 1; } STFS_FragmentFileMetadata *lp_Ffm = lp_Efm->GetFragment(lv_FragmentOffset); if(!lp_Ffm) { errno = ENOENT; char lp_ErrMess[] = "Error obtaining fragment"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -4; } STFS_ExternalFileHandle *lp_Efh = lp_Efm->Open(true); if (!lp_Efh) { // TBD cleanup errno = ENOENT; char lp_ErrMess[] = "Error allocating EFH"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -5; } lv_Ret = StoreOpenerInfo(lp_Efm, pv_OpenerNodeId, pv_OpenerPID, pp_OpenId); if (lv_Ret < 0) { //TBD cleanup errno = ENOENT; char lp_ErrMess[] = "Error storing opener information"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -6; } pp_Efm = lp_Efm; pp_Ffm = lp_Ffm; //Build Success Reply return 0; }
int STFSLIB_close(stfs_fhndl_t pv_Fhandle) { const char *WHERE = "STFSLIB_close"; STFS_ScopeTrace lv_st(WHERE); STFS_ExternalFileHandle *lp_Efh = STFS_ExternalFileHandle::GetExternalFileHandle(pv_Fhandle); if (! lp_Efh) { errno = EBADF; TRACE_PRINTF2(1, "Error in obtaining External File Handle for %ld\n", pv_Fhandle); return -1; } lp_Efh->ResetErrors(); /// Rev: Do we close . Set the state. Continue on errors. // Closes the fragments int lv_Ret = lp_Efh->Close(); if (lv_Ret < 0) { TRACE_PRINTF3(1, "Error %d while closing handle: %ld\n", lv_Ret, pv_Fhandle); // continue on error when closing } STFS_ExternalFileMetadata *lp_Efm = lp_Efh->EfmGet(); if (!lp_Efm) { // corruption in some STFS maintained data structures. STFS_util::SoftwareFailureHandler(WHERE); return -1; } lv_Ret = lp_Efm->Close(false); if (lv_Ret < 0) { TRACE_PRINTF3(1,"Error %d while closing handle: %ld\n", lv_Ret, pv_Fhandle); return -1; } lv_Ret = STFS_ExternalFileMetadata::DeleteFromContainer(lp_Efm); if (lv_Ret < 0) { STFS_util::SoftwareFailureHandler(WHERE); return lv_Ret; } // send message to the STFS daemon #ifdef SQ_PACK lv_Ret = SendToSTFSd_close(&(lp_Efh->OpenIdentifierGet()), STFS_util::GetMyNodeId(), STFS_util::GetMyPID()); if (lv_Ret < 0) { // 'errno' should be set here return lv_Ret; } #else lv_Ret = STFSd_close(&(lp_Efh->OpenIdentifierGet())); if (lv_Ret < 0) { return lv_Ret; } #endif // remove Efh from the Container lv_Ret = STFS_ExternalFileHandle::DeleteFromContainer(lp_Efh); if (lv_Ret < 0) { STFS_util::SoftwareFailureHandler(WHERE); return lv_Ret; } return 0; }
/////////////////////////////////////////////////////////////////////////////// /// // 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; }
/////////////////////////////////////////////////////////////////////////////// /// // STFSd_mkstemp /// /// \brief Processes an mkstemp request /// - Generates an external file name /// /// \param int *pp_Ctemplate, /// \param int pv_OpenerNodeId, /// \param int pv_OpenerPID, /// \param STFS_ExternalFileMetadata *&pp_Efm, /// \param STFS_OpenIdentifier *&pp_OpenId) /// /// /////////////////////////////////////////////////////////////////////////////// int STFSd_mkstemp(char *pp_Ctemplate, int pv_OpenerNodeId, int pv_OpenerPID, STFS_ExternalFileMetadata *&pp_Efm, STFS_OpenIdentifier *&pp_OpenId) { ///////////////////////////////// /// parameter checking and housekeeping ///////////////////////////////// const char *WHERE = "STFSd_mkstemp"; STFS_ScopeTrace lv_st(WHERE); STFS_Session *lp_Session = STFS_Session::GetSession(); int lv_Ret = 0; if (!pp_Ctemplate) { errno = EFAULT; lp_Session->SetError(true, errno, 0, NULL, 0); return -1; } /// Generate the file name lv_Ret = STFS_util::GenerateExternalFilename(pp_Ctemplate); if (lv_Ret < 0) { errno = EINVAL; char lp_ErrMess[] = "Error generating external file name"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -2; } ///////////////////////////////// /// Reserve the name ///////////////////////////////// // We're the owning daemon process, so we need to reserve the name lv_Ret = STFS_File::ReserveName (pp_Ctemplate); if (lv_Ret<0) { errno = EIO; char lp_ErrMess[] = "Error while reserving name"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); //name exists? Couldn't talk to the disk? WhatEVer... Hope that //ReserveName packed the error correctly... return -6; } ///////////////////////////////// /// Create the EFM for the file ///////////////////////////////// STFS_ExternalFileMetadata *lp_Efm = new STFS_ExternalFileMetadata(pp_Ctemplate, STFS_util::GetMyNodeId()); if (lp_Efm == NULL) { //Could not find/allocate EFM, probably doesn't exist errno = ENOENT; char lp_ErrMess[] = "Error allocating EFM"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); //UhOh, couldn't allocate an EFM! Gotta free the directory we created STFS_File::ReleaseName (pp_Ctemplate); // return -7; } TRACE_PRINTF4(2, "FileName: %s, Opener Node Id: %d, Opener SQ PID: %d\n", lp_Efm->ExternalFileNameGet(), pv_OpenerNodeId, pv_OpenerPID); ///////////////////////////////// ///insert EFM in a global map ///////////////////////////////// lv_Ret = STFS_ExternalFileMetadata::InsertIntoContainer(lp_Efm); if (lv_Ret < 0) { //TBD cleanup //Could not insert into EFM Container... errno = ENOMEM; char lp_ErrMess[] = "Error Insertnig EFM into EFM Container"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -4; } ///////////////////////////////// /// Store the opener info in the EFM ///////////////////////////////// lv_Ret = StoreOpenerInfo(lp_Efm, pv_OpenerNodeId, pv_OpenerPID, pp_OpenId); if (lv_Ret < 0) { //TBD cleanup //Could not store opener information errno = ENOMEM; char lp_ErrMess[] = "Error storing opener information"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -5; } ///////////////////////////////// /// Create the fragment ///////////////////////////////// if (STFSd_createFragment(lp_Efm, pv_OpenerNodeId, pv_OpenerPID, 0) < 0) { //Could not create fragment errno = EIO; char lp_ErrMess[] = "Error creating fragment"; lp_Session->SetError(true, errno, 0, lp_ErrMess, strlen(lp_ErrMess)); return -3; } STFS_util::ValidateEFM(lp_Efm); pp_Efm = lp_Efm; return 0; }
// Rev: Missing doxygen hdr stfs_fhndl_t STFSLIB_mkstemp(char *pp_Ctemplate) { const char *WHERE = "STFSLIB_mkstemp"; STFS_ScopeTrace lv_st(WHERE); // Rev: Add an ASSERT for pp_Ctemplate if (!pp_Ctemplate) { return -1; } STFS_ExternalFileMetadata *lp_Efm = 0; STFS_FragmentFileMetadata *lp_Ffm = 0; STFS_OpenIdentifier *lp_OpenId = 0; int lv_ret = 0; #ifdef SQ_PACK lv_ret = SendToSTFSd_mkstemp(pp_Ctemplate, STFS_util::GetMyNodeId(), STFS_util::GetMyPID(), lp_Efm, lp_OpenId); #else lv_ret = STFSd_mkstemp(pp_Ctemplate, STFS_util::GetMyNodeId(), STFS_util::GetMyPID(), lp_Efm, lp_OpenId); #endif // lp_OpenID was NEW'd in SendToSTFSd_mkstemp. We need to free it // here after we're done. Really, we should allocate and free at // the same level... // Rev: Check for (!= 0) if (lv_ret < 0) { // Rev: Add ASSERTs to check that lp_Efm, lp_OpenId are NULL delete lp_OpenId; return lv_ret; } // Rev: Remove this and add ASSERTs for lp_Efm/lp_OpenId being not NULL if (!lp_Efm) { delete lp_OpenId; return -1; } if (!lp_Efm->IsEyeCatcherValid()) { delete lp_OpenId; STFS_util::SoftwareFailureHandler(WHERE); return -1; } // Rev: Remove this STFS_util::ValidateEFM(lp_Efm); STFS_ExternalFileHandle *lp_Efh = lp_Efm->Open(false); if (!lp_Efh) { //TBD cleanup // Rev: Send a message to the STFSd to cleanup/ delete directories delete lp_OpenId; return -1; } lp_Efh->OpenFlagsSet(O_RDWR); lp_Efh->OpenIdentifierSet(*lp_OpenId); //Rev: Valgrind shows that there is a memory leak here. However if the following 'delete' // is uncommented then our tests fail with SQ_PACK=0; and SQ_STFSD=0. Need to figure // out what is the cause of the tests failing in order to allow this memory leak fix. //delete lp_OpenId; lp_Ffm = lp_Efm->GetFragment (0); // This is mkstemp, so there's only one fragment! // Rev: Check for lp_Ffm STFS_FragmentFileHandle *lp_Ffh = new STFS_FragmentFileHandle(lp_Ffm); // Rev: Check for lp_Ffh lp_Efh->InsertFFH(lp_Ffh); //Rev: Did the Insert work? return (stfs_fhndl_t) lp_Efh; }
////////////////////////////////////////////////////////////////////////////// /// // STFSLIB_read /// /// \brief Driver code for an STFS_read() library call /// ////////////////////////////////////////////////////////////////////////////// ssize_t STFSLIB_read( stfs_fhndl_t pv_Fhandle, void *pp_Buf, size_t pv_Count) { const char *WHERE = "STFSLIB_read"; STFS_ScopeTrace lv_st(WHERE); if (!pp_Buf) { errno = EFAULT; return -1; } STFS_ExternalFileHandle *lp_Efh = STFS_ExternalFileHandle::GetExternalFileHandle(pv_Fhandle); if (! lp_Efh) { TRACE_PRINTF2(1, "Error in obtaining External File Handle for %ld\n", pv_Fhandle); return -1; } lp_Efh->ResetErrors(); size_t lv_totalBytesRead = 0; bool lv_readCompleted = false; char * lp_currBufPtr = (char *) pp_Buf; size_t lv_readSize = pv_Count; while (!lv_readCompleted) { ssize_t lv_Stat = 0; int lv_Ret = 0; //Check if the current fragment is local. If not, then send req to daemon lv_Ret = lp_Efh->IsCurrFragmentLocal(); if(lv_Ret < 0) { //error evaluating fragment return -1; } else if(lv_Ret == 1) { lv_Stat = lp_Efh->Read((char *)lp_currBufPtr, lv_readSize); } else { #ifdef SQ_PACK lv_Stat= SendToSTFSd_read(); #else lv_Stat = STFSd_read(&(lp_Efh->OpenIdentifierGet()), (char *)lp_currBufPtr, lv_readSize); #endif //The currentFFH_ is not local so we will need to read // through remote daemon } if (( (size_t)lv_Stat + lv_totalBytesRead) == pv_Count) { // the usual case; we read everything as expected. Prepare to exit our // read-loop lv_totalBytesRead += lv_Stat; lv_readCompleted = true; } else if (lv_Stat == 0) { // Didn't read anything else in this fragment. Can we roll to another? // Gotcha! There might be a new fragment here! Check to see if there // are any new fragments then loop around and read again. // If we're moving to a new FFH that's already in our list, the // reposition at the top of the loop should move to it automatically, // so we just skip ahead. // // But if this is the last FFH, we need to see if either this process // or the owning STFSd knows about any more fragments. We take a lazy // approach to doing this, hoping that somewhere along the way, // someone has already retrieved this information for us: // // 1) See if the EFM already knows about other fragments. Occurs // this process owns read access to the file in another open, or // another opener in this process already got an updated list of // FFMs. // // 2) If the number of FFHs matches the number of FFMs and we're in // the last FFM, check with the owning daemon to update the // metadata for this file. if (lp_Efh->CurrentFFHIsLast() == true) { if (lp_Efh->NewFFHsNeeded() == true) { // Someone else found fragments for us. Logically open them for // this efh and try the read again. lv_Stat = lp_Efh ->OpenNewFragments(); if (lv_Stat < 0) { return (lv_totalBytesRead>0 ? lv_totalBytesRead : lv_Stat); } } else { // We have all the FFHs that this lib process knows about, // check to see if new fragments available bool lv_newFragsDetected = LibRead_GetMoreFragments (lp_Efh); if (lv_newFragsDetected == false) { // a real EOF! Clean up errno after all the calls we've made errno = 0; return lv_totalBytesRead; } // We found new fragments. Open them and try to read the rest of // the data. lv_Stat = lp_Efh ->OpenNewFragments(); if (lv_Stat < 0) { // hope that any error was set below return (lv_totalBytesRead>0 ? lv_totalBytesRead : -1); } } // else } } // 0 count error handling else if (lv_Stat<0) { // Error! We might be done here. We can't just return this error // though. We have to check to see if we read anything. If so, return // that value and when the caller comes back, the error might (or might // not) happen again. return (lv_totalBytesRead>0 ? lv_totalBytesRead : -1); } else { // partial read! Adjust our counters and try again // find out... ASSERT ( (size_t) lv_Stat < pv_Count); lv_totalBytesRead += lv_Stat; lp_currBufPtr = (char *)lp_currBufPtr + lv_Stat; lv_readSize -= lv_Stat; } if (lp_Efh->SetCurrentFragmentBasedOnCurrOffset() == true) { // switched frags! We're reading sequentially, so we need to do an // explicit lseek in case this fragment's FD was previously used for // some other I/O operation. lv_Stat = lp_Efh->SeekToCurrFragmentStart(); if (lv_Stat < 0) { // physical position failed! return (lv_totalBytesRead>0 ? lv_totalBytesRead : lv_Stat); } } } //while !readcompleted return lv_totalBytesRead; }