PageRenderTime 42ms CodeModel.GetById 18ms app.highlight 20ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llvfs/llpidlock.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 276 lines | 197 code | 48 blank | 31 comment | 15 complexity | 7d4176f33441d70d14234b53fbdb2e63 MD5 | raw file
  1/** 
  2 * @file llformat.cpp
  3 * @date   January 2007
  4 * @brief string formatting utility
  5 *
  6 * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  7 * Second Life Viewer Source Code
  8 * Copyright (C) 2010, Linden Research, Inc.
  9 * 
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation;
 13 * version 2.1 of the License only.
 14 * 
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23 * 
 24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25 * $/LicenseInfo$
 26 */
 27
 28#include "linden_common.h"
 29
 30#include "llpidlock.h"
 31#include "lldir.h"
 32#include "llsd.h"
 33#include "llsdserialize.h"
 34#include "llnametable.h"
 35#include "llframetimer.h"
 36
 37#if LL_WINDOWS   //For windows platform.
 38
 39#include <windows.h>
 40
 41namespace {
 42	inline DWORD getpid() {
 43		return GetCurrentProcessId();
 44	}
 45}
 46
 47bool isProcessAlive(U32 pid)
 48{
 49	return (bool) GetProcessVersion((DWORD)pid);
 50}
 51
 52#else   //Everyone Else
 53bool isProcessAlive(U32 pid)
 54{   
 55	return (bool) kill( (pid_t)pid, 0);
 56}
 57#endif //Everyone else.
 58
 59
 60	
 61class LLPidLockFile
 62{
 63	public:
 64		LLPidLockFile( ) :
 65			mAutosave(false),
 66			mSaving(false),
 67			mWaiting(false),
 68			mPID(getpid()),
 69			mNameTable(NULL),
 70			mClean(true)
 71		{
 72			mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
 73		}
 74		bool requestLock(LLNameTable<void *> *name_table, bool autosave,
 75						bool force_immediate=FALSE, F32 timeout=300.0);
 76		bool checkLock();
 77		void releaseLock();
 78
 79	private:
 80		void writeLockFile(LLSD pids);
 81	public:
 82		static LLPidLockFile& instance(); // return the singleton black list file
 83			 
 84		bool mAutosave;
 85		bool mSaving;
 86		bool mWaiting;
 87		LLFrameTimer mTimer;
 88		U32  mPID;
 89		std::string mLockName;
 90		std::string mSaveName;
 91		LLSD mPIDS_sd;
 92		LLNameTable<void*> *mNameTable;
 93		bool mClean;
 94};
 95
 96LLPidLockFile& LLPidLockFile::instance()
 97{   
 98	static LLPidLockFile the_file;
 99	return the_file;
100}
101
102void LLPidLockFile::writeLockFile(LLSD pids)
103{
104	llofstream ofile(mLockName);
105
106	if (!LLSDSerialize::toXML(pids,ofile))
107	{
108		llwarns << "Unable to write concurrent save lock file." << llendl;
109	}
110	ofile.close();
111}
112
113bool LLPidLockFile::requestLock(LLNameTable<void *> *name_table, bool autosave,
114								bool force_immediate, F32 timeout)
115{
116	bool readyToSave = FALSE;
117
118	if (mSaving) return FALSE;	//Bail out if we're currently saving.  Will not queue another save.
119	
120	if (!mWaiting){
121		mNameTable=name_table;
122		mAutosave = autosave;
123	}
124
125	LLSD out_pids;
126	out_pids.append( (LLSD::Integer)mPID );
127
128	llifstream ifile(mLockName);
129
130	if (ifile.is_open()) 
131	{									//If file exists, we need to decide whether or not to continue.
132		if ( force_immediate
133			|| mTimer.hasExpired() )	//Only deserialize if we REALLY need to.
134		{
135
136			LLSD in_pids;
137
138			LLSDSerialize::fromXML(in_pids, ifile);	
139
140			//Clean up any dead PIDS that might be in there.
141			for (LLSD::array_iterator i=in_pids.beginArray();
142				i !=in_pids.endArray();
143				++i)
144			{
145				U32 stored_pid=(*i).asInteger();
146
147				if (isProcessAlive(stored_pid))
148				{
149					out_pids.append( (*i) );
150				}
151			}
152
153			readyToSave=TRUE;
154		}
155		ifile.close();
156	}
157	else
158	{
159		readyToSave=TRUE;
160	}
161
162	if (!mWaiting)				//Not presently waiting to save.  Queue up.
163	{
164		mTimer.resetWithExpiry(timeout);
165		mWaiting=TRUE;
166	}
167
168	if (readyToSave)
169	{	//Potential race condition won't kill us. Ignore it.
170		writeLockFile(out_pids);
171		mSaving=TRUE;
172	}
173	
174	return readyToSave;
175}
176
177bool LLPidLockFile::checkLock()
178{
179	return mWaiting;
180}
181
182void LLPidLockFile::releaseLock()
183{
184	llifstream ifile(mLockName);
185	LLSD in_pids;
186	LLSD out_pids;
187	bool write_file=FALSE;
188
189	LLSDSerialize::fromXML(in_pids, ifile);	
190
191	//Clean up this PID and any dead ones.
192	for (LLSD::array_iterator i=in_pids.beginArray();
193		i !=in_pids.endArray();
194		++i)
195	{
196		U32 stored_pid=(*i).asInteger();
197
198		if (stored_pid != mPID && isProcessAlive(stored_pid))
199		{
200			out_pids.append( (*i) );
201			write_file=TRUE;
202		}
203	}
204	ifile.close();
205
206	if (write_file)
207	{
208		writeLockFile(out_pids);
209	}
210	else
211	{
212		unlink(mLockName.c_str());
213	}
214
215	mSaving=FALSE;
216	mWaiting=FALSE;
217}
218
219//LLPidLock
220
221void LLPidLock::initClass() { 
222	(void) LLPidLockFile::instance(); 
223}
224
225bool LLPidLock::checkLock() 
226{
227	return LLPidLockFile::instance().checkLock();
228}
229
230bool LLPidLock::requestLock(LLNameTable<void *> *name_table, bool autosave,
231								bool force_immediate, F32 timeout)
232{
233	return LLPidLockFile::instance().requestLock(name_table,autosave,force_immediate,timeout);
234}
235
236void LLPidLock::releaseLock() 
237{ 
238	return LLPidLockFile::instance().releaseLock(); 
239}
240
241bool LLPidLock::isClean() 
242{ 
243	return LLPidLockFile::instance().mClean; 
244}
245
246//getters
247LLNameTable<void *> * LLPidLock::getNameTable() 
248{ 
249    return LLPidLockFile::instance().mNameTable; 
250}
251
252bool LLPidLock::getAutosave() 
253{ 
254	return LLPidLockFile::instance().mAutosave; 
255}
256
257bool LLPidLock::getClean() 
258{ 
259	return LLPidLockFile::instance().mClean; 
260}
261
262std::string LLPidLock::getSaveName() 
263{ 
264	return LLPidLockFile::instance().mSaveName; 
265}
266
267//setters
268void LLPidLock::setClean(bool clean) 
269{ 
270	LLPidLockFile::instance().mClean=clean; 
271}
272
273void LLPidLock::setSaveName(std::string savename) 
274{ 
275	LLPidLockFile::instance().mSaveName=savename; 
276}