llxfer_vfile.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llxfer_vfile.h"
00035 #include "lluuid.h"
00036 #include "llerror.h"
00037 #include "llmath.h"
00038 #include "llvfile.h"
00039 #include "llvfs.h"
00040 #include "lldir.h"
00041 
00042 // size of chunks read from/written to disk
00043 const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
00044 
00046 
00047 LLXfer_VFile::LLXfer_VFile ()
00048 : LLXfer(-1)
00049 {
00050         init(NULL, LLUUID::null, LLAssetType::AT_NONE);
00051 }
00052 
00053 LLXfer_VFile::LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
00054 : LLXfer(-1)
00055 {
00056         init(vfs, local_id, type);
00057 }
00058 
00060 
00061 LLXfer_VFile::~LLXfer_VFile ()
00062 {
00063         free();
00064 }
00065 
00067 
00068 void LLXfer_VFile::init (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
00069 {
00070 
00071         mVFS = vfs;
00072         mLocalID = local_id;
00073         mType = type;
00074 
00075         mVFile = NULL;
00076 
00077         char id_string[UUID_STR_LENGTH];                        /* Flawfinder : ignore */
00078         mLocalID.toString(id_string);
00079 
00080         snprintf(mName, sizeof(mName), "VFile %s:%s", id_string, LLAssetType::lookup(mType));           /* Flawfinder : ignore */
00081 }
00082         
00084 
00085 void LLXfer_VFile::free ()
00086 {
00087         LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
00088         file.remove();
00089 
00090         delete mVFile;
00091         mVFile = NULL;
00092 
00093         LLXfer::free();
00094 }
00095 
00097 
00098 S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
00099                                                                         LLVFS* vfs,
00100                                                                         const LLUUID& local_id,
00101                                                                         const LLUUID& remote_id,
00102                                                                         LLAssetType::EType type,
00103                                                                         const LLHost& remote_host,
00104                                                                         void (*callback)(void**,S32,LLExtStat),
00105                                                                         void** user_data)
00106 {
00107         S32 retval = 0;  // presume success
00108         
00109         mRemoteHost = remote_host;
00110 
00111         mVFS = vfs;
00112         mLocalID = local_id;
00113         mRemoteID = remote_id;
00114         mType = type;
00115 
00116         mID = xfer_id;
00117         mCallback = callback;
00118         mCallbackDataHandle = user_data;
00119         mCallbackResult = LL_ERR_NOERR;
00120 
00121         char id_string[UUID_STR_LENGTH];                /* Flawfinder : ignore */
00122         mLocalID.toString(id_string);
00123 
00124         snprintf(mName, sizeof(mName), "VFile %s:%s", id_string, LLAssetType::lookup(mType));           /* Flawfinder : ignore */
00125 
00126         llinfos << "Requesting " << mName << llendl;
00127 
00128         if (mBuffer)
00129         {
00130                 delete[] mBuffer;
00131                 mBuffer = NULL;
00132         }
00133 
00134         mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
00135 
00136         mBufferLength = 0;
00137         mPacketNum = 0;
00138         mTempID.generate();
00139         mStatus = e_LL_XFER_PENDING;
00140         return retval;
00141 }
00142 
00144 
00145 S32 LLXfer_VFile::startDownload()
00146 {
00147         S32 retval = 0;  // presume success
00148         LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
00149 
00150         gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
00151         gMessageSystem->nextBlockFast(_PREHASH_XferID);
00152         gMessageSystem->addU64Fast(_PREHASH_ID, mID);
00153         gMessageSystem->addStringFast(_PREHASH_Filename, "");
00154         gMessageSystem->addU8("FilePath", (U8) LL_PATH_NONE);
00155         gMessageSystem->addBOOL("DeleteOnCompletion", FALSE);
00156         gMessageSystem->addBOOL("UseBigPackets", BOOL(mChunkSize == LL_XFER_LARGE_PAYLOAD));
00157         gMessageSystem->addUUIDFast(_PREHASH_VFileID, mRemoteID);
00158         gMessageSystem->addS16Fast(_PREHASH_VFileType, (S16)mType);
00159 
00160         gMessageSystem->sendReliable(mRemoteHost);              
00161         mStatus = e_LL_XFER_IN_PROGRESS;
00162 
00163         return (retval);
00164 }
00165 
00167 
00168 S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
00169 {
00170         S32 retval = LL_ERR_NOERR;  // presume success
00171         
00172     mRemoteHost = remote_host;
00173         mID = xfer_id;
00174         mPacketNum = -1;
00175 
00176 //      cout << "Sending file: " << mLocalFilename << endl;
00177 
00178         delete [] mBuffer;
00179         mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
00180 
00181         mBufferLength = 0;
00182         mBufferStartOffset = 0; 
00183         
00184         delete mVFile;
00185         mVFile = NULL;
00186         if(mVFS->getExists(mLocalID, mType))
00187         {
00188                 mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ);
00189 
00190                 if (mVFile->getSize() <= 0)
00191                 {
00192                         delete mVFile;
00193                         mVFile = NULL;
00194 
00195                         return LL_ERR_FILE_EMPTY;
00196                 }
00197         }
00198 
00199         if(mVFile)
00200         {
00201                 setXferSize(mVFile->getSize());
00202                 mStatus = e_LL_XFER_PENDING;
00203         }
00204         else
00205         {
00206                 retval = LL_ERR_FILE_NOT_FOUND;
00207         }
00208 
00209         return (retval);
00210 }
00211 
00213 void LLXfer_VFile::setXferSize (S32 xfer_size)
00214 {       
00215         LLXfer::setXferSize(xfer_size);
00216 
00217         // Don't do this on the server side, where we have a persistent mVFile
00218         // It would be nice if LLXFers could tell which end of the pipe they were
00219         if (! mVFile)
00220         {
00221                 LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
00222                 file.setMaxSize(xfer_size);
00223         }
00224 }
00225 
00227 
00228 S32 LLXfer_VFile::getMaxBufferSize ()
00229 {
00230         return(LL_MAX_XFER_FILE_BUFFER);
00231 }
00232 
00234 
00235 S32 LLXfer_VFile::suck(S32 start_position)
00236 {
00237         S32 retval = 0;
00238 
00239         if (mVFile)
00240         {
00241                 // grab a buffer from the right place in the file
00242                 if (! mVFile->seek(start_position, 0))
00243                 {
00244                         llwarns << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << llendl;
00245                         llwarns << "While sending file " << mLocalID << llendl;
00246                         return -1;
00247                 }
00248                 
00249                 if (mVFile->read((U8*)mBuffer, LL_MAX_XFER_FILE_BUFFER))                /* Flawfinder : ignore */
00250                 {
00251                         mBufferLength = mVFile->getLastBytesRead();
00252                         mBufferStartOffset = start_position;
00253 
00254                         mBufferContainsEOF = mVFile->eof();
00255                 }
00256                 else
00257                 {
00258                         retval = -1;
00259                 }
00260         }
00261         else
00262         {
00263                 retval = -1;
00264         }
00265 
00266         return (retval);
00267 }
00268 
00270 
00271 S32 LLXfer_VFile::flush()
00272 {
00273         S32 retval = 0;
00274         if (mBufferLength)
00275         {
00276                 LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
00277 
00278                 file.write((U8*)mBuffer, mBufferLength);
00279                         
00280                 mBufferLength = 0;
00281         }
00282         return (retval);
00283 }
00284 
00286 
00287 S32 LLXfer_VFile::processEOF()
00288 {
00289         S32 retval = 0;
00290         mStatus = e_LL_XFER_COMPLETE;
00291 
00292         flush();
00293 
00294         if (!mCallbackResult)
00295         {
00296                 LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
00297                 if (! file.rename(mLocalID, mType))
00298                 {
00299                         llinfos << "copy from temp file failed: unable to rename to " << mLocalID << llendl;
00300                 }
00301 
00302         }
00303 
00304         if (mVFile)
00305         {
00306                 delete mVFile;
00307                 mVFile = NULL;
00308         }
00309 
00310         retval = LLXfer::processEOF();
00311 
00312         return(retval);
00313 }
00314 
00316 
00317 BOOL LLXfer_VFile::matchesLocalFile(const LLUUID &id, LLAssetType::EType type)
00318 {
00319         return (id == mLocalID && type == mType);
00320 }
00321 
00323 
00324 BOOL LLXfer_VFile::matchesRemoteFile(const LLUUID &id, LLAssetType::EType type)
00325 {
00326         return (id == mRemoteID && type == mType);
00327 }
00328 
00330 
00331 const char * LLXfer_VFile::getName() 
00332 {
00333         return mName;
00334 }
00335 
00337 
00338 // hacky - doesn't matter what this is
00339 // as long as it's different from the other classes
00340 U32 LLXfer_VFile::getXferTypeTag()
00341 {
00342         return LLXfer::XFER_VFILE;
00343 }

Generated on Thu Jul 1 06:09:48 2010 for Second Life Viewer by  doxygen 1.4.7