diff options
author | Brad Kittenbrink <brad@lindenlab.com> | 2021-12-15 17:06:24 -0800 |
---|---|---|
committer | Brad Kittenbrink <brad@lindenlab.com> | 2021-12-15 17:06:24 -0800 |
commit | 1e6caa69e6576a87bb0b1b782bffdd0697fa0c2d (patch) | |
tree | 38f8f0136381a2e7f2b8fcba82d9781bdfab9273 /indra/llvfs/llvfile.cpp | |
parent | 95e2f6286c140b6d3a7562a7e73f70d0ab60685b (diff) | |
parent | 0a873cd95547f003878c6d00d0883ff792f4a865 (diff) |
Merge remote-tracking branch 'origin/master' into brad/DRTVWR-550-mfa
Diffstat (limited to 'indra/llvfs/llvfile.cpp')
-rw-r--r-- | indra/llvfs/llvfile.cpp | 437 |
1 files changed, 0 insertions, 437 deletions
diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp deleted file mode 100644 index b8588e99f4..0000000000 --- a/indra/llvfs/llvfile.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/** - * @file llvfile.cpp - * @brief Implementation of virtual file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llvfile.h" - -#include "llerror.h" -#include "llthread.h" -#include "lltimer.h" -#include "llfasttimer.h" -#include "llmemory.h" -#include "llvfs.h" - -const S32 LLVFile::READ = 0x00000001; -const S32 LLVFile::WRITE = 0x00000002; -const S32 LLVFile::READ_WRITE = 0x00000003; // LLVFile::READ & LLVFile::WRITE -const S32 LLVFile::APPEND = 0x00000006; // 0x00000004 & LLVFile::WRITE - -static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); - -//---------------------------------------------------------------------------- -LLVFSThread* LLVFile::sVFSThread = NULL; -BOOL LLVFile::sAllocdVFSThread = FALSE; -//---------------------------------------------------------------------------- - -//============================================================================ - -LLVFile::LLVFile(LLVFS *vfs, const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode) -{ - mFileType = file_type; - - mFileID = file_id; - mPosition = 0; - mMode = mode; - mVFS = vfs; - - mBytesRead = 0; - mHandle = LLVFSThread::nullHandle(); - mPriority = 128.f; - - mVFS->incLock(mFileID, mFileType, VFSLOCK_OPEN); -} - -LLVFile::~LLVFile() -{ - if (!isReadComplete()) - { - if (mHandle != LLVFSThread::nullHandle()) - { - if (!(mMode & LLVFile::WRITE)) - { - //LL_WARNS() << "Destroying LLVFile with pending async read/write, aborting..." << LL_ENDL; - sVFSThread->setFlags(mHandle, LLVFSThread::FLAG_AUTO_COMPLETE | LLVFSThread::FLAG_ABORT); - } - else // WRITE - { - sVFSThread->setFlags(mHandle, LLVFSThread::FLAG_AUTO_COMPLETE); - } - } - } - mVFS->decLock(mFileID, mFileType, VFSLOCK_OPEN); -} - -BOOL LLVFile::read(U8 *buffer, S32 bytes, BOOL async, F32 priority) -{ - if (! (mMode & READ)) - { - LL_WARNS() << "Attempt to read from file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL; - return FALSE; - } - - if (mHandle != LLVFSThread::nullHandle()) - { - LL_WARNS() << "Attempt to read from vfile object " << mFileID << " with pending async operation" << LL_ENDL; - return FALSE; - } - mPriority = priority; - - BOOL success = TRUE; - - // We can't do a read while there are pending async writes - waitForLock(VFSLOCK_APPEND); - - // *FIX: (?) - if (async) - { - mHandle = sVFSThread->read(mVFS, mFileID, mFileType, buffer, mPosition, bytes, threadPri()); - } - else - { - // We can't do a read while there are pending async writes on this file - mBytesRead = sVFSThread->readImmediate(mVFS, mFileID, mFileType, buffer, mPosition, bytes); - mPosition += mBytesRead; - if (! mBytesRead) - { - success = FALSE; - } - } - - return success; -} - -//static -U8* LLVFile::readFile(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, S32* bytes_read) -{ - U8 *data; - LLVFile file(vfs, uuid, type, LLVFile::READ); - S32 file_size = file.getSize(); - if (file_size == 0) - { - // File is empty. - data = NULL; - } - else - { - data = (U8*) ll_aligned_malloc<16>(file_size); - file.read(data, file_size); /* Flawfinder: ignore */ - - if (file.getLastBytesRead() != (S32)file_size) - { - ll_aligned_free<16>(data); - data = NULL; - file_size = 0; - } - } - if (bytes_read) - { - *bytes_read = file_size; - } - return data; -} - -void LLVFile::setReadPriority(const F32 priority) -{ - mPriority = priority; - if (mHandle != LLVFSThread::nullHandle()) - { - sVFSThread->setPriority(mHandle, threadPri()); - } -} - -BOOL LLVFile::isReadComplete() -{ - BOOL res = TRUE; - if (mHandle != LLVFSThread::nullHandle()) - { - LLVFSThread::Request* req = (LLVFSThread::Request*)sVFSThread->getRequest(mHandle); - LLVFSThread::status_t status = req->getStatus(); - if (status == LLVFSThread::STATUS_COMPLETE) - { - mBytesRead = req->getBytesRead(); - mPosition += mBytesRead; - sVFSThread->completeRequest(mHandle); - mHandle = LLVFSThread::nullHandle(); - } - else - { - res = FALSE; - } - } - return res; -} - -S32 LLVFile::getLastBytesRead() -{ - return mBytesRead; -} - -BOOL LLVFile::eof() -{ - return mPosition >= getSize(); -} - -BOOL LLVFile::write(const U8 *buffer, S32 bytes) -{ - if (! (mMode & WRITE)) - { - LL_WARNS() << "Attempt to write to file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL; - } - if (mHandle != LLVFSThread::nullHandle()) - { - LL_ERRS() << "Attempt to write to vfile object " << mFileID << " with pending async operation" << LL_ENDL; - return FALSE; - } - BOOL success = TRUE; - - // *FIX: allow async writes? potential problem wit mPosition... - if (mMode == APPEND) // all appends are async (but WRITEs are not) - { - U8* writebuf = new U8[bytes]; - memcpy(writebuf, buffer, bytes); - S32 offset = -1; - mHandle = sVFSThread->write(mVFS, mFileID, mFileType, - writebuf, offset, bytes, - LLVFSThread::FLAG_AUTO_COMPLETE | LLVFSThread::FLAG_AUTO_DELETE); - mHandle = LLVFSThread::nullHandle(); // FLAG_AUTO_COMPLETE means we don't track this - } - else - { - // We can't do a write while there are pending reads or writes on this file - waitForLock(VFSLOCK_READ); - waitForLock(VFSLOCK_APPEND); - - S32 pos = (mMode & APPEND) == APPEND ? -1 : mPosition; - - S32 wrote = sVFSThread->writeImmediate(mVFS, mFileID, mFileType, (U8*)buffer, pos, bytes); - - mPosition += wrote; - - if (wrote < bytes) - { - LL_WARNS() << "Tried to write " << bytes << " bytes, actually wrote " << wrote << LL_ENDL; - - success = FALSE; - } - } - return success; -} - -//static -BOOL LLVFile::writeFile(const U8 *buffer, S32 bytes, LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type) -{ - LLVFile file(vfs, uuid, type, LLVFile::WRITE); - file.setMaxSize(bytes); - return file.write(buffer, bytes); -} - -BOOL LLVFile::seek(S32 offset, S32 origin) -{ - if (mMode == APPEND) - { - LL_WARNS() << "Attempt to seek on append-only file" << LL_ENDL; - return FALSE; - } - - if (-1 == origin) - { - origin = mPosition; - } - - S32 new_pos = origin + offset; - - S32 size = getSize(); // Calls waitForLock(VFSLOCK_APPEND) - - if (new_pos > size) - { - LL_WARNS() << "Attempt to seek past end of file" << LL_ENDL; - - mPosition = size; - return FALSE; - } - else if (new_pos < 0) - { - LL_WARNS() << "Attempt to seek past beginning of file" << LL_ENDL; - - mPosition = 0; - return FALSE; - } - - mPosition = new_pos; - return TRUE; -} - -S32 LLVFile::tell() const -{ - return mPosition; -} - -S32 LLVFile::getSize() -{ - waitForLock(VFSLOCK_APPEND); - S32 size = mVFS->getSize(mFileID, mFileType); - - return size; -} - -S32 LLVFile::getMaxSize() -{ - S32 size = mVFS->getMaxSize(mFileID, mFileType); - - return size; -} - -BOOL LLVFile::setMaxSize(S32 size) -{ - if (! (mMode & WRITE)) - { - LL_WARNS() << "Attempt to change size of file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL; - - return FALSE; - } - - if (!mVFS->checkAvailable(size)) - { - //LL_RECORD_BLOCK_TIME(FTM_VFILE_WAIT); - S32 count = 0; - while (sVFSThread->getPending() > 1000) - { - if (count % 100 == 0) - { - LL_INFOS() << "VFS catching up... Pending: " << sVFSThread->getPending() << LL_ENDL; - } - if (sVFSThread->isPaused()) - { - sVFSThread->update(0); - } - ms_sleep(10); - } - } - return mVFS->setMaxSize(mFileID, mFileType, size); -} - -BOOL LLVFile::rename(const LLUUID &new_id, const LLAssetType::EType new_type) -{ - if (! (mMode & WRITE)) - { - LL_WARNS() << "Attempt to rename file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL; - - return FALSE; - } - - if (mHandle != LLVFSThread::nullHandle()) - { - LL_WARNS() << "Renaming file with pending async read" << LL_ENDL; - } - - waitForLock(VFSLOCK_READ); - waitForLock(VFSLOCK_APPEND); - - // we need to release / replace our own lock - // since the renamed file will inherit locks from the new name - mVFS->decLock(mFileID, mFileType, VFSLOCK_OPEN); - mVFS->renameFile(mFileID, mFileType, new_id, new_type); - mVFS->incLock(new_id, new_type, VFSLOCK_OPEN); - - mFileID = new_id; - mFileType = new_type; - - return TRUE; -} - -BOOL LLVFile::remove() -{ -// LL_INFOS() << "Removing file " << mFileID << LL_ENDL; - - if (! (mMode & WRITE)) - { - // Leaving paranoia warning just because this should be a very infrequent - // operation. - LL_WARNS() << "Remove file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL; - } - - if (mHandle != LLVFSThread::nullHandle()) - { - LL_WARNS() << "Removing file with pending async read" << LL_ENDL; - } - - // why not seek back to the beginning of the file too? - mPosition = 0; - - waitForLock(VFSLOCK_READ); - waitForLock(VFSLOCK_APPEND); - mVFS->removeFile(mFileID, mFileType); - - return TRUE; -} - -// static -void LLVFile::initClass(LLVFSThread* vfsthread) -{ - if (!vfsthread) - { - if (LLVFSThread::sLocal != NULL) - { - vfsthread = LLVFSThread::sLocal; - } - else - { - vfsthread = new LLVFSThread(); - sAllocdVFSThread = TRUE; - } - } - sVFSThread = vfsthread; -} - -// static -void LLVFile::cleanupClass() -{ - if (sAllocdVFSThread) - { - delete sVFSThread; - } - sVFSThread = NULL; -} - -bool LLVFile::isLocked(EVFSLock lock) -{ - return mVFS->isLocked(mFileID, mFileType, lock) ? true : false; -} - -void LLVFile::waitForLock(EVFSLock lock) -{ - //LL_RECORD_BLOCK_TIME(FTM_VFILE_WAIT); - // spin until the lock clears - while (isLocked(lock)) - { - if (sVFSThread->isPaused()) - { - sVFSThread->update(0); - } - ms_sleep(1); - } -} |