From ce0dbbd8a543a32e033eb15888259151ca113539 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 2 Apr 2013 12:57:09 -0400
Subject: [PATCH] Add reporting of last_exec_duration (and clean up logic
 around multiple instances)

---
 indra/newview/llappviewer.cpp     | 107 +++++++++++++++++-------------
 indra/newview/llappviewer.h       |   3 +-
 indra/newview/lllogininstance.cpp |   1 +
 indra/newview/lllogininstance.h   |   2 +
 indra/newview/llstartup.cpp       |   2 +
 5 files changed, 69 insertions(+), 46 deletions(-)

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e3a2fae7ef5..effe7b74909 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -270,6 +270,7 @@ BOOL gShowObjectUpdates = FALSE;
 BOOL gUseQuickTime = TRUE;
 
 eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
+S32 gLastExecDuration = -1; // (<0 indicates unknown) 
 
 #if LL_WINDOWS  
 #   define LL_PLATFORM_KEY "win"
@@ -340,6 +341,7 @@ BOOL gLogoutInProgress = FALSE;
 static std::string gArgs;
 const int MAX_MARKER_LENGTH = 1024;
 const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
+const std::string START_MARKER_FILE_NAME("SecondLife.start_marker");
 const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
 const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
 const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
@@ -2112,7 +2114,7 @@ void errorCallback(const std::string &error_string)
 	LLError::crashAndLoop(error_string);
 }
 
-bool LLAppViewer::initLogging()
+void LLAppViewer::initLogging()
 {
 	//
 	// Set up logging defaults for the viewer
@@ -2126,17 +2128,46 @@ bool LLAppViewer::initLogging()
 							     "SecondLife.old");
 	LLFile::remove(old_log_file);
 
-	// Rename current log file to ".old"
+	// Get name of the log file
 	std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
 							     "SecondLife.log");
+	/*
+	 * Before touching any log files, compute the duration of the last run
+	 * by comparing the ctime of the previous start marker file with the ctime
+	 * of the last log file.
+	 */
+	std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME);
+	llstat start_marker_stat;
+	llstat log_file_stat;
+	if (   0 == LLFile::stat(start_marker_file_name, &start_marker_stat)
+		&& 0 == LLFile::stat(log_file, &log_file_stat)
+		)
+	{
+		int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime;
+		// only report a last run time if the last viewer was the same version
+		// because this stat will be counted against this version
+		gLastExecDuration = markerIsSameVersion(start_marker_file_name) ? elapsed_seconds : -1;
+	}
+	else
+	{
+		// at least one of the LLFile::stat calls failed, so we can't compute the run time
+		gLastExecDuration = -1; // unknown
+	}
+	
+	// Create a new start marker file for comparison with log file time for the next run
+	LLAPRFile start_marker_file ;
+	start_marker_file.open(start_marker_file_name, LL_APR_W);
+	if (start_marker_file.getFileHandle())
+	{
+		recordMarkerVersion(start_marker_file);
+		start_marker_file.close();
+	}
+
+	// Rename current log file to ".old"
 	LLFile::rename(log_file, old_log_file);
 
 	// Set the log file to SecondLife.log
-
 	LLError::logToFile(log_file);
-
-	// *FIX:Mani no error handling here!
-	return true;
 }
 
 bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
@@ -2711,51 +2742,37 @@ bool LLAppViewer::initConfiguration()
 		}
 	}
 
-	if (!gSavedSettings.getBOOL("AllowMultipleViewers"))
+	//
+	// Check for another instance of the app running
+	//
+	mSecondInstance = anotherInstanceRunning();
+	if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers"))
 	{
-	    //
-	    // Check for another instance of the app running
-	    //
-
-		mSecondInstance = anotherInstanceRunning();
-		
-		if (mSecondInstance)
-		{
-			std::ostringstream msg;
-			msg << LLTrans::getString("MBAlreadyRunning");
-			OSMessageBox(
-				msg.str(),
-				LLStringUtil::null,
-				OSMB_OK);
-			return false;
-		}
+		std::ostringstream msg;
+		msg << LLTrans::getString("MBAlreadyRunning");
+		OSMessageBox(
+			msg.str(),
+			LLStringUtil::null,
+			OSMB_OK);
+		return false;
+	}
 
-		initMarkerFile();
+	initMarkerFile();
         
-        checkForCrash();
-    }
-	else
+	if (mSecondInstance)
 	{
-		mSecondInstance = anotherInstanceRunning();
-		
-		if (mSecondInstance)
+		// This is the second instance of SL. Turn off voice support,
+		// but make sure the setting is *not* persisted.
+		LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
+		if(disable_voice)
 		{
-			// This is the second instance of SL. Turn off voice support,
-			// but make sure the setting is *not* persisted.
-			LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
-			if(disable_voice)
-			{
-				const BOOL DO_NOT_PERSIST = FALSE;
-				disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
-			}
+			const BOOL DO_NOT_PERSIST = FALSE;
+			disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
 		}
-
-		initMarkerFile();
-        
-        if(!mSecondInstance)
-        {
-            checkForCrash();
-        }
+	}
+	else
+	{
+		checkForCrash();
 	}
 
    	// NextLoginLocation is set from the command line option
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index c8fb0231501..84cfcf6922b 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -183,7 +183,7 @@ class LLAppViewer : public LLApp
 	
 protected:
 	virtual bool initWindow(); // Initialize the viewer's window.
-	virtual bool initLogging(); // Initialize log files, logging system, return false on failure.
+	virtual void initLogging(); // Initialize log files, logging system
 	virtual void initConsole() {}; // Initialize OS level debugging console.
 	virtual bool initHardwareTest() { return true; } // A false result indicates the app should quit.
 	virtual bool initSLURLHandler();
@@ -323,6 +323,7 @@ typedef enum
 } eLastExecEvent;
 
 extern eLastExecEvent gLastExecEvent; // llstartup
+extern S32 gLastExecDuration; ///< the duration of the previous run in seconds (<0 indicates unknown)
 
 extern const char* gPlatform;
 
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 71c07d6381b..977c50682fe 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -596,6 +596,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 	request_params["agree_to_tos"] = false; // Always false here. Set true in 
 	request_params["read_critical"] = false; // handleTOSResponse
 	request_params["last_exec_event"] = mLastExecEvent;
+	request_params["last_exec_duration"] = mLastExecDuration;
 	request_params["mac"] = (char*)hashed_unique_id_string;
 	request_params["version"] = LLVersionInfo::getVersion();
 	request_params["channel"] = LLVersionInfo::getChannel();
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 83191e50bdf..b0247da7c83 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -66,6 +66,7 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	void setSkipOptionalUpdate(bool state) { mSkipOptionalUpdate = state; }
 	void setSerialNumber(const std::string& sn) { mSerialNumber = sn; }
 	void setLastExecEvent(int lee) { mLastExecEvent = lee; }
+	void setLastExecDuration(S32 duration) { mLastExecDuration = duration; }
 	void setPlatformInfo(const std::string platform, const std::string platform_version);
 
 	void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; }
@@ -100,6 +101,7 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	F64 mTransferRate;
 	std::string mSerialNumber;
 	int mLastExecEvent;
+	S32 mLastExecDuration;
 	std::string mPlatform;
 	std::string mPlatformVersion;
 	UpdaterLauncherCallback mUpdaterLauncher;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 37e6ded986f..f52aedda9f4 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -26,6 +26,7 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llappviewer.h"
 #include "llstartup.h"
 
 #if LL_WINDOWS
@@ -1043,6 +1044,7 @@ bool idle_startup()
 
 		login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
 		login->setLastExecEvent(gLastExecEvent);
+		login->setLastExecDuration(gLastExecDuration);
 		login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance()));
 
 		// This call to LLLoginInstance::connect() starts the 
-- 
GitLab