diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llmessage/llxfer_vfile.cpp |
Print done when done.
Diffstat (limited to 'indra/llmessage/llxfer_vfile.cpp')
-rw-r--r-- | indra/llmessage/llxfer_vfile.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/indra/llmessage/llxfer_vfile.cpp b/indra/llmessage/llxfer_vfile.cpp new file mode 100644 index 0000000000..5030556eb0 --- /dev/null +++ b/indra/llmessage/llxfer_vfile.cpp @@ -0,0 +1,320 @@ +/** + * @file llxfer_vfile.cpp + * @brief implementation of LLXfer_VFile class for a single xfer (vfile). + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "llxfer_vfile.h" +#include "lluuid.h" +#include "llerror.h" +#include "llmath.h" +#include "llvfile.h" +#include "llvfs.h" +#include "lldir.h" + +// size of chunks read from/written to disk +const U32 LL_MAX_XFER_FILE_BUFFER = 65536; + +/////////////////////////////////////////////////////////// + +LLXfer_VFile::LLXfer_VFile () +: LLXfer(-1) +{ + init(NULL, LLUUID::null, LLAssetType::AT_NONE); +} + +LLXfer_VFile::LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type) +: LLXfer(-1) +{ + init(vfs, local_id, type); +} + +/////////////////////////////////////////////////////////// + +LLXfer_VFile::~LLXfer_VFile () +{ + free(); +} + +/////////////////////////////////////////////////////////// + +void LLXfer_VFile::init (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type) +{ + + mVFS = vfs; + mLocalID = local_id; + mType = type; + + mVFile = NULL; + + char id_string[UUID_STR_LENGTH]; /* Flawfinder : ignore */ + mLocalID.toString(id_string); + + snprintf(mName, sizeof(mName), "VFile %s:%s", id_string, LLAssetType::lookup(mType)); /* Flawfinder : ignore */ +} + +/////////////////////////////////////////////////////////// + +void LLXfer_VFile::free () +{ + LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); + file.remove(); + + delete mVFile; + mVFile = NULL; + + LLXfer::free(); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::initializeRequest(U64 xfer_id, + LLVFS* vfs, + const LLUUID& local_id, + const LLUUID& remote_id, + LLAssetType::EType type, + const LLHost& remote_host, + void (*callback)(void**,S32), + void** user_data) +{ + S32 retval = 0; // presume success + + mRemoteHost = remote_host; + + mVFS = vfs; + mLocalID = local_id; + mRemoteID = remote_id; + mType = type; + + mID = xfer_id; + mCallback = callback; + mCallbackDataHandle = user_data; + mCallbackResult = LL_ERR_NOERR; + + char id_string[UUID_STR_LENGTH]; /* Flawfinder : ignore */ + mLocalID.toString(id_string); + + snprintf(mName, sizeof(mName), "VFile %s:%s", id_string, LLAssetType::lookup(mType)); /* Flawfinder : ignore */ + + llinfos << "Requesting " << mName << llendl; + + if (mBuffer) + { + delete[] mBuffer; + mBuffer = NULL; + } + + mBuffer = new char[LL_MAX_XFER_FILE_BUFFER]; + + mBufferLength = 0; + mPacketNum = 0; + mTempID.generate(); + mStatus = e_LL_XFER_PENDING; + return retval; +} + +////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::startDownload() +{ + S32 retval = 0; // presume success + LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND); + + gMessageSystem->newMessageFast(_PREHASH_RequestXfer); + gMessageSystem->nextBlockFast(_PREHASH_XferID); + gMessageSystem->addU64Fast(_PREHASH_ID, mID); + gMessageSystem->addStringFast(_PREHASH_Filename, ""); + gMessageSystem->addU8("FilePath", (U8) LL_PATH_NONE); + gMessageSystem->addBOOL("DeleteOnCompletion", FALSE); + gMessageSystem->addBOOL("UseBigPackets", BOOL(mChunkSize == LL_XFER_LARGE_PAYLOAD)); + gMessageSystem->addUUIDFast(_PREHASH_VFileID, mRemoteID); + gMessageSystem->addS16Fast(_PREHASH_VFileType, (S16)mType); + + gMessageSystem->sendReliable(mRemoteHost); + mStatus = e_LL_XFER_IN_PROGRESS; + + return (retval); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host) +{ + S32 retval = LL_ERR_NOERR; // presume success + + mRemoteHost = remote_host; + mID = xfer_id; + mPacketNum = -1; + +// cout << "Sending file: " << mLocalFilename << endl; + + delete [] mBuffer; + mBuffer = new char[LL_MAX_XFER_FILE_BUFFER]; + + mBufferLength = 0; + mBufferStartOffset = 0; + + delete mVFile; + mVFile = NULL; + if(mVFS->getExists(mLocalID, mType)) + { + mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ); + + if (mVFile->getSize() <= 0) + { + delete mVFile; + mVFile = NULL; + + return LL_ERR_FILE_EMPTY; + } + } + + if(mVFile) + { + setXferSize(mVFile->getSize()); + mStatus = e_LL_XFER_PENDING; + } + else + { + retval = LL_ERR_FILE_NOT_FOUND; + } + + return (retval); +} + +/////////////////////////////////////////////////////////// +void LLXfer_VFile::setXferSize (S32 xfer_size) +{ + LLXfer::setXferSize(xfer_size); + + // Don't do this on the server side, where we have a persistent mVFile + // It would be nice if LLXFers could tell which end of the pipe they were + if (! mVFile) + { + LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND); + file.setMaxSize(xfer_size); + } +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::getMaxBufferSize () +{ + return(LL_MAX_XFER_FILE_BUFFER); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::suck(S32 start_position) +{ + S32 retval = 0; + + if (mVFile) + { + // grab a buffer from the right place in the file + if (! mVFile->seek(start_position, 0)) + { + llwarns << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << llendl; + llwarns << "While sending file " << mLocalID << llendl; + return -1; + } + + if (mVFile->read((U8*)mBuffer, LL_MAX_XFER_FILE_BUFFER)) /* Flawfinder : ignore */ + { + mBufferLength = mVFile->getLastBytesRead(); + mBufferStartOffset = start_position; + + mBufferContainsEOF = mVFile->eof(); + } + else + { + retval = -1; + } + } + else + { + retval = -1; + } + + return (retval); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::flush() +{ + S32 retval = 0; + if (mBufferLength) + { + LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND); + + file.write((U8*)mBuffer, mBufferLength); + + mBufferLength = 0; + } + return (retval); +} + +/////////////////////////////////////////////////////////// + +S32 LLXfer_VFile::processEOF() +{ + S32 retval = 0; + mStatus = e_LL_XFER_COMPLETE; + + flush(); + + if (!mCallbackResult) + { + LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); + if (! file.rename(mLocalID, mType)) + { + llinfos << "copy from temp file failed: unable to rename to " << mLocalID << llendl; + } + + } + + if (mVFile) + { + delete mVFile; + mVFile = NULL; + } + + retval = LLXfer::processEOF(); + + return(retval); +} + +//////////////////////////////////////////////////////////// + +BOOL LLXfer_VFile::matchesLocalFile(const LLUUID &id, LLAssetType::EType type) +{ + return (id == mLocalID && type == mType); +} + +////////////////////////////////////////////////////////// + +BOOL LLXfer_VFile::matchesRemoteFile(const LLUUID &id, LLAssetType::EType type) +{ + return (id == mRemoteID && type == mType); +} + +////////////////////////////////////////////////////////// + +const char * LLXfer_VFile::getName() +{ + return mName; +} + +////////////////////////////////////////////////////////// + +// hacky - doesn't matter what this is +// as long as it's different from the other classes +U32 LLXfer_VFile::getXferTypeTag() +{ + return LLXfer::XFER_VFILE; +} |