diff options
Diffstat (limited to 'indra/llvfs/llpidlock.cpp')
-rwxr-xr-x | indra/llvfs/llpidlock.cpp | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp new file mode 100755 index 0000000000..e231002a52 --- /dev/null +++ b/indra/llvfs/llpidlock.cpp @@ -0,0 +1,268 @@ +/** + * @file llformat.cpp + * @date January 2007 + * @brief string formatting utility + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpidlock.h" +#include "lldir.h" +#include "llsd.h" +#include "llsdserialize.h" +#include "llnametable.h" +#include "llframetimer.h" + +#if LL_WINDOWS //For windows platform. +bool isProcessAlive(U32 pid) +{ + return (bool) GetProcessVersion((DWORD)pid); +} + +#else //Everyone Else +bool isProcessAlive(U32 pid) +{ + return (bool) kill( (pid_t)pid, 0); +} +#endif //Everyone else. + + + +class LLPidLockFile +{ + public: + LLPidLockFile( ) : + mSaving(FALSE), mWaiting(FALSE), + mClean(TRUE), mPID(getpid()) + { + mLockName = gDirUtilp->getTempDir() + "/savelock"; + } + bool requestLock(LLNameTable<void *> *name_table, bool autosave, + bool force_immediate=FALSE, F32 timeout=300.0); + bool checkLock(); + void releaseLock(); + + private: + void writeLockFile(LLSD pids); + public: + static LLPidLockFile& instance(); // return the singleton black list file + + bool mAutosave; + bool mSaving; + bool mWaiting; + LLFrameTimer mTimer; + U32 mPID; + std::string mLockName; + std::string mSaveName; + LLSD mPIDS_sd; + LLNameTable<void*> *mNameTable; + bool mClean; +}; + +LLPidLockFile& LLPidLockFile::instance() +{ + static LLPidLockFile the_file; + return the_file; +} + +void LLPidLockFile::writeLockFile(LLSD pids) +{ + llofstream ofile(mLockName); + + if (!LLSDSerialize::toXML(pids,ofile)) + { + llwarns << "Unable to write concurrent save lock file." << llendl; + } + ofile.close(); +} + +bool LLPidLockFile::requestLock(LLNameTable<void *> *name_table, bool autosave, + bool force_immediate, F32 timeout) +{ + bool readyToSave = FALSE; + + if (mSaving) return FALSE; //Bail out if we're currently saving. Will not queue another save. + + if (!mWaiting){ + mNameTable=name_table; + mAutosave = autosave; + } + + LLSD out_pids; + out_pids.append( (LLSD::Integer)mPID ); + + llifstream ifile(mLockName); + + if (ifile.is_open()) + { //If file exists, we need to decide whether or not to continue. + if ( force_immediate + || mTimer.hasExpired() ) //Only deserialize if we REALLY need to. + { + + LLSD in_pids; + + LLSDSerialize::fromXML(in_pids, ifile); + + //Clean up any dead PIDS that might be in there. + for (LLSD::array_iterator i=in_pids.beginArray(); + i !=in_pids.endArray(); + ++i) + { + U32 stored_pid=(*i).asInteger(); + + if (isProcessAlive(stored_pid)) + { + out_pids.append( (*i) ); + } + } + + readyToSave=TRUE; + } + ifile.close(); + } + else + { + readyToSave=TRUE; + } + + if (!mWaiting) //Not presently waiting to save. Queue up. + { + mTimer.resetWithExpiry(timeout); + mWaiting=TRUE; + } + + if (readyToSave) + { //Potential race condition won't kill us. Ignore it. + writeLockFile(out_pids); + mSaving=TRUE; + } + + return readyToSave; +} + +bool LLPidLockFile::checkLock() +{ + return mWaiting; +} + +void LLPidLockFile::releaseLock() +{ + llifstream ifile(mLockName); + LLSD in_pids; + LLSD out_pids; + bool write_file=FALSE; + + LLSDSerialize::fromXML(in_pids, ifile); + + //Clean up this PID and any dead ones. + for (LLSD::array_iterator i=in_pids.beginArray(); + i !=in_pids.endArray(); + ++i) + { + U32 stored_pid=(*i).asInteger(); + + if (stored_pid != mPID && isProcessAlive(stored_pid)) + { + out_pids.append( (*i) ); + write_file=TRUE; + } + } + ifile.close(); + + if (write_file) + { + writeLockFile(out_pids); + } + else + { + unlink(mLockName.c_str()); + } + + mSaving=FALSE; + mWaiting=FALSE; +} + +//LLPidLock + +void LLPidLock::initClass() { + (void) LLPidLockFile::instance(); +} + +bool LLPidLock::checkLock() +{ + return LLPidLockFile::instance().checkLock(); +} + +bool LLPidLock::requestLock(LLNameTable<void *> *name_table, bool autosave, + bool force_immediate, F32 timeout) +{ + return LLPidLockFile::instance().requestLock(name_table,autosave,force_immediate,timeout); +} + +void LLPidLock::releaseLock() +{ + return LLPidLockFile::instance().releaseLock(); +} + +bool LLPidLock::isClean() +{ + return LLPidLockFile::instance().mClean; +} + +//getters +LLNameTable<void *> * LLPidLock::getNameTable() +{ + return LLPidLockFile::instance().mNameTable; +} + +bool LLPidLock::getAutosave() +{ + return LLPidLockFile::instance().mAutosave; +} + +bool LLPidLock::getClean() +{ + return LLPidLockFile::instance().mClean; +} + +std::string LLPidLock::getSaveName() +{ + return LLPidLockFile::instance().mSaveName; +} + +//setters +void LLPidLock::setClean(bool clean) +{ + LLPidLockFile::instance().mClean=clean; +} + +void LLPidLock::setSaveName(std::string savename) +{ + LLPidLockFile::instance().mSaveName=savename; +} |