summaryrefslogtreecommitdiff
path: root/indra/llvfs/llvfile.cpp
diff options
context:
space:
mode:
authorBrad Kittenbrink <brad@lindenlab.com>2021-12-15 17:06:24 -0800
committerBrad Kittenbrink <brad@lindenlab.com>2021-12-15 17:06:24 -0800
commit1e6caa69e6576a87bb0b1b782bffdd0697fa0c2d (patch)
tree38f8f0136381a2e7f2b8fcba82d9781bdfab9273 /indra/llvfs/llvfile.cpp
parent95e2f6286c140b6d3a7562a7e73f70d0ab60685b (diff)
parent0a873cd95547f003878c6d00d0883ff792f4a865 (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.cpp437
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);
- }
-}