PageRenderTime 176ms CodeModel.GetById 26ms RepoModel.GetById 0ms 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
Possible License(s): LGPL-2.1
  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. #include "linden_common.h"
  28. #include "llpidlock.h"
  29. #include "lldir.h"
  30. #include "llsd.h"
  31. #include "llsdserialize.h"
  32. #include "llnametable.h"
  33. #include "llframetimer.h"
  34. #if LL_WINDOWS //For windows platform.
  35. #include <windows.h>
  36. namespace {
  37. inline DWORD getpid() {
  38. return GetCurrentProcessId();
  39. }
  40. }
  41. bool isProcessAlive(U32 pid)
  42. {
  43. return (bool) GetProcessVersion((DWORD)pid);
  44. }
  45. #else //Everyone Else
  46. bool isProcessAlive(U32 pid)
  47. {
  48. return (bool) kill( (pid_t)pid, 0);
  49. }
  50. #endif //Everyone else.
  51. class LLPidLockFile
  52. {
  53. public:
  54. LLPidLockFile( ) :
  55. mAutosave(false),
  56. mSaving(false),
  57. mWaiting(false),
  58. mPID(getpid()),
  59. mNameTable(NULL),
  60. mClean(true)
  61. {
  62. mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
  63. }
  64. bool requestLock(LLNameTable<void *> *name_table, bool autosave,
  65. bool force_immediate=FALSE, F32 timeout=300.0);
  66. bool checkLock();
  67. void releaseLock();
  68. private:
  69. void writeLockFile(LLSD pids);
  70. public:
  71. static LLPidLockFile& instance(); // return the singleton black list file
  72. bool mAutosave;
  73. bool mSaving;
  74. bool mWaiting;
  75. LLFrameTimer mTimer;
  76. U32 mPID;
  77. std::string mLockName;
  78. std::string mSaveName;
  79. LLSD mPIDS_sd;
  80. LLNameTable<void*> *mNameTable;
  81. bool mClean;
  82. };
  83. LLPidLockFile& LLPidLockFile::instance()
  84. {
  85. static LLPidLockFile the_file;
  86. return the_file;
  87. }
  88. void LLPidLockFile::writeLockFile(LLSD pids)
  89. {
  90. llofstream ofile(mLockName);
  91. if (!LLSDSerialize::toXML(pids,ofile))
  92. {
  93. llwarns << "Unable to write concurrent save lock file." << llendl;
  94. }
  95. ofile.close();
  96. }
  97. bool LLPidLockFile::requestLock(LLNameTable<void *> *name_table, bool autosave,
  98. bool force_immediate, F32 timeout)
  99. {
  100. bool readyToSave = FALSE;
  101. if (mSaving) return FALSE; //Bail out if we're currently saving. Will not queue another save.
  102. if (!mWaiting){
  103. mNameTable=name_table;
  104. mAutosave = autosave;
  105. }
  106. LLSD out_pids;
  107. out_pids.append( (LLSD::Integer)mPID );
  108. llifstream ifile(mLockName);
  109. if (ifile.is_open())
  110. { //If file exists, we need to decide whether or not to continue.
  111. if ( force_immediate
  112. || mTimer.hasExpired() ) //Only deserialize if we REALLY need to.
  113. {
  114. LLSD in_pids;
  115. LLSDSerialize::fromXML(in_pids, ifile);
  116. //Clean up any dead PIDS that might be in there.
  117. for (LLSD::array_iterator i=in_pids.beginArray();
  118. i !=in_pids.endArray();
  119. ++i)
  120. {
  121. U32 stored_pid=(*i).asInteger();
  122. if (isProcessAlive(stored_pid))
  123. {
  124. out_pids.append( (*i) );
  125. }
  126. }
  127. readyToSave=TRUE;
  128. }
  129. ifile.close();
  130. }
  131. else
  132. {
  133. readyToSave=TRUE;
  134. }
  135. if (!mWaiting) //Not presently waiting to save. Queue up.
  136. {
  137. mTimer.resetWithExpiry(timeout);
  138. mWaiting=TRUE;
  139. }
  140. if (readyToSave)
  141. { //Potential race condition won't kill us. Ignore it.
  142. writeLockFile(out_pids);
  143. mSaving=TRUE;
  144. }
  145. return readyToSave;
  146. }
  147. bool LLPidLockFile::checkLock()
  148. {
  149. return mWaiting;
  150. }
  151. void LLPidLockFile::releaseLock()
  152. {
  153. llifstream ifile(mLockName);
  154. LLSD in_pids;
  155. LLSD out_pids;
  156. bool write_file=FALSE;
  157. LLSDSerialize::fromXML(in_pids, ifile);
  158. //Clean up this PID and any dead ones.
  159. for (LLSD::array_iterator i=in_pids.beginArray();
  160. i !=in_pids.endArray();
  161. ++i)
  162. {
  163. U32 stored_pid=(*i).asInteger();
  164. if (stored_pid != mPID && isProcessAlive(stored_pid))
  165. {
  166. out_pids.append( (*i) );
  167. write_file=TRUE;
  168. }
  169. }
  170. ifile.close();
  171. if (write_file)
  172. {
  173. writeLockFile(out_pids);
  174. }
  175. else
  176. {
  177. unlink(mLockName.c_str());
  178. }
  179. mSaving=FALSE;
  180. mWaiting=FALSE;
  181. }
  182. //LLPidLock
  183. void LLPidLock::initClass() {
  184. (void) LLPidLockFile::instance();
  185. }
  186. bool LLPidLock::checkLock()
  187. {
  188. return LLPidLockFile::instance().checkLock();
  189. }
  190. bool LLPidLock::requestLock(LLNameTable<void *> *name_table, bool autosave,
  191. bool force_immediate, F32 timeout)
  192. {
  193. return LLPidLockFile::instance().requestLock(name_table,autosave,force_immediate,timeout);
  194. }
  195. void LLPidLock::releaseLock()
  196. {
  197. return LLPidLockFile::instance().releaseLock();
  198. }
  199. bool LLPidLock::isClean()
  200. {
  201. return LLPidLockFile::instance().mClean;
  202. }
  203. //getters
  204. LLNameTable<void *> * LLPidLock::getNameTable()
  205. {
  206. return LLPidLockFile::instance().mNameTable;
  207. }
  208. bool LLPidLock::getAutosave()
  209. {
  210. return LLPidLockFile::instance().mAutosave;
  211. }
  212. bool LLPidLock::getClean()
  213. {
  214. return LLPidLockFile::instance().mClean;
  215. }
  216. std::string LLPidLock::getSaveName()
  217. {
  218. return LLPidLockFile::instance().mSaveName;
  219. }
  220. //setters
  221. void LLPidLock::setClean(bool clean)
  222. {
  223. LLPidLockFile::instance().mClean=clean;
  224. }
  225. void LLPidLock::setSaveName(std::string savename)
  226. {
  227. LLPidLockFile::instance().mSaveName=savename;
  228. }