Initial Commit
This commit is contained in:
316
TomcatServer/PlutoServer.MSL/AutoUpdate.cs
Normal file
316
TomcatServer/PlutoServer.MSL/AutoUpdate.cs
Normal file
@@ -0,0 +1,316 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Yaulw.File;
|
||||
using System.IO;
|
||||
using Yaulw.Thread;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PlutoServer.MSL
|
||||
{
|
||||
internal static class AutoUpdate
|
||||
{
|
||||
#region Private Statics
|
||||
|
||||
/// <summary>
|
||||
/// Check every 2.5 hours
|
||||
/// </summary>
|
||||
private const int AUTO_CHECK_INTERVAL_IN_MINUTES = 150;
|
||||
|
||||
/// <summary>
|
||||
/// Keep track when last update occured
|
||||
/// </summary>
|
||||
private static ISReadWrite s_ISReadWrite = new ISReadWrite("update");
|
||||
|
||||
/// <summary>
|
||||
/// Auto-Update Thread
|
||||
/// </summary>
|
||||
private static SingleThreadTimer timer = null;
|
||||
|
||||
/// <summary>
|
||||
/// Online Version of the Service
|
||||
/// </summary>
|
||||
private static Version OnlineVersion = null;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the LocalFileNameNPath for SetupMini File (TEMP FOLDER)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string MiniSetupFileNameNPath
|
||||
{
|
||||
get
|
||||
{
|
||||
string LocalFileNameNPath = Yaulw.Tools.PathNaming.PathEndsWithSlash(Path.GetTempPath()) + "SetupMini.exe";
|
||||
return LocalFileNameNPath;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
static AutoUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region internal Methods
|
||||
|
||||
/// <summary>
|
||||
/// Try to update the Service, if needed
|
||||
/// </summary>
|
||||
internal static void TryToUpdateIfNeeded(int nDelay, bool bCheckDTStamp)
|
||||
{
|
||||
// Default Auto Update with 15 sec delay
|
||||
if (nDelay < 0)
|
||||
nDelay = 15;
|
||||
|
||||
PlutoService.AppLogInfo(String.Format("TryToUpdateIfNeeded called at {0} with delay {1} and CheckDT {2}", DateTime.Now.ToLongTimeString(), nDelay.ToString(), bCheckDTStamp));
|
||||
if (bCheckDTStamp)
|
||||
{
|
||||
DateTime dtLastUpdated = GetLastUpdated();
|
||||
TimeSpan ts = DateTime.Now - dtLastUpdated;
|
||||
if (ts.TotalDays >= 1.0)
|
||||
{
|
||||
PlutoService.AppLogInfo(String.Format("LaunchUpdateThread called with Delay {0}", nDelay));
|
||||
LaunchUpdateThread(nDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlutoService.AppLogInfo(String.Format("LaunchUpdateThread called with Delay {0}", nDelay));
|
||||
LaunchUpdateThread(nDelay);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main Entry Point - Service Calls into here upon Start-Up
|
||||
/// </summary>
|
||||
internal static void StartAutoTimer_ServiceStarted()
|
||||
{
|
||||
// Important Sanity Clean-up, this way we know that the service
|
||||
// always downloads the latest setup and runs the latest setup
|
||||
if (File.Exists(MiniSetupFileNameNPath))
|
||||
File.Delete(MiniSetupFileNameNPath);
|
||||
|
||||
// Right at Service Startup Check if we have tried to update
|
||||
// within the last day, if we have not, try to update.
|
||||
// NOTE: Don't do this if we just got installed for the very first time
|
||||
// the service seems to hang when doing that during the install of
|
||||
// lytec/medisoft. (not known what the root cause is), but let's
|
||||
// just avoid it alltogether. (We could potentially add a timeout here
|
||||
// and just check way way later), not sure what the best course of action
|
||||
// is at this point.
|
||||
DateTime dt = Yaulw.Registry.RegKey.GetKey<DateTime>(Yaulw.Registry.HKEYRoot.LocalMachine, PlutoService.LOCAL_MACHINE_SUBKEY, PlutoService.LOCAL_MACHINE_INITIALSETUPDT, DateTime.MinValue);
|
||||
TimeSpan ts = DateTime.Now - dt;
|
||||
|
||||
// If the ts is < 10 Minutes we must have just gotten installed, hence, we shouldn't
|
||||
// try to update the service and just let it start (let the autoUpdate Handler below or Diagnose Mobile handle the initial updating).
|
||||
if (ts.TotalMinutes > 10)
|
||||
TryToUpdateIfNeeded(0, false);
|
||||
|
||||
// Additionally, we want to start a Timer Thread,
|
||||
// that Randomly checks for new updates, once every few hours, but only
|
||||
// in specific circumstances will it actually perform the update. ( check every 2.5 hours )
|
||||
timer = new SingleThreadTimer(AutoUpdateHandler, (uint)TimeSpan.FromMinutes(AUTO_CHECK_INTERVAL_IN_MINUTES).TotalMilliseconds, true);
|
||||
// * for debugging *:
|
||||
//SingleThreadTimer timer = new SingleThreadTimer(STElapsedEventHandler, (uint)TimeSpan.FromSeconds(30).TotalMilliseconds, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main Entry Point - Service Calls into here upon Stop
|
||||
/// </summary>
|
||||
internal static void StopAutoTimer_ServiceStopped()
|
||||
{
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Stop();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetch the Latest Version that is Online
|
||||
/// </summary>
|
||||
/// <returns>valid version object or null if error occured</returns>
|
||||
internal static Version FetchOnlineVerion()
|
||||
{
|
||||
string fetchVersion = Yaulw.Net.WCHelper.ScreenScrapeFromURL(Configuration.CHECK_VERSION_URL);
|
||||
if (!String.IsNullOrEmpty(fetchVersion))
|
||||
{
|
||||
fetchVersion = fetchVersion.Replace("\n", "");
|
||||
fetchVersion = fetchVersion.Replace("\r", "");
|
||||
fetchVersion = fetchVersion.Trim();
|
||||
|
||||
try
|
||||
{
|
||||
Version version = new Version(fetchVersion);
|
||||
return version;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PlutoService.AppLogError(String.Format("The url:{0} to check the Mobile version could not be parsed: {1}", Configuration.CHECK_VERSION_URL, e.Message));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlutoService.AppLogError(String.Format("The url:{0} to check the Mobile version could not be accessed", Configuration.CHECK_VERSION_URL));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quick Check to see if the Local Service is out of date
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static bool IsLocalServiceVersionOutOfDate()
|
||||
{
|
||||
OnlineVersion = FetchOnlineVerion();
|
||||
Version LocalVersion = Yaulw.Assembly.AssemblyW.GetAssemblyVersion(Yaulw.Assembly.AssemblyW.AssemblyST.Entry);
|
||||
if (OnlineVersion != null && LocalVersion != null)
|
||||
{
|
||||
if (OnlineVersion.Major == LocalVersion.Major && OnlineVersion > LocalVersion)
|
||||
{
|
||||
PlutoService.AppLogInfo("Newer Mobile Api Service Found Online");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlutoService.AppLogInfo("Mobile Api Service is already up to date");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods / Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Called Randomly every 2.5 Hours, will call Update only if called in the hours of 2 am - 6am AND
|
||||
/// the TimeSpan of the last update has been over a day
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void AutoUpdateHandler(object sender, Yaulw.Thread.SingleThreadTimer.STElapsedEventArgs e)
|
||||
{
|
||||
DateTime dt = e.SignalTime.ToLocalTime();
|
||||
TimeSpan ts = dt.TimeOfDay;
|
||||
bool bIsBetween2amAnd6am = (ts.TotalHours >= 2.0) && (ts.TotalHours <= 6.0);
|
||||
|
||||
// Only Check between the hours of 2am to 6am
|
||||
// And if we haven't updated today yet
|
||||
if (bIsBetween2amAnd6am)
|
||||
{
|
||||
// Launch update without a thread, already inside a thread
|
||||
TryToUpdateIfNeeded(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the LastUpdated() DT or DateTime.Min if none
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static DateTime GetLastUpdated()
|
||||
{
|
||||
string s = s_ISReadWrite.ReadFromIS();
|
||||
DateTime dt = DateTime.MinValue;
|
||||
if (!String.IsNullOrEmpty(s) && DateTime.TryParse(s, out dt))
|
||||
return dt;
|
||||
else
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the LastUpdated() DT
|
||||
/// </summary>
|
||||
/// <param name="dt"></param>
|
||||
private static void SetLastUpdated(DateTime dt)
|
||||
{
|
||||
if (dt != null)
|
||||
{
|
||||
s_ISReadWrite.WriteToIS(dt.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add A Delay variable to the Update Thread
|
||||
/// </summary>
|
||||
private class UpdateThreadParams
|
||||
{
|
||||
public int nDelay = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for Updates and update the service if needed
|
||||
/// </summary>
|
||||
private static void CheckForUpdatesAndUpdate(object o)
|
||||
{
|
||||
int nSleepInMiliseconds = 0;
|
||||
if (o != null)
|
||||
{
|
||||
UpdateThreadParams p = (UpdateThreadParams)o;
|
||||
nSleepInMiliseconds = p.nDelay;
|
||||
}
|
||||
|
||||
PlutoService.AppLogInfo(string.Format("CheckForUpdatesAndUpdate called with nDelay {0}", nSleepInMiliseconds));
|
||||
if(nSleepInMiliseconds > 0)
|
||||
System.Threading.Thread.Sleep(nSleepInMiliseconds);
|
||||
|
||||
// Update this service, if Online Version is bigger than Local Version
|
||||
if (IsLocalServiceVersionOutOfDate())
|
||||
{
|
||||
if (Yaulw.Net.WCHelper.DownloadFileFromURL(Configuration.DOWNLOAD_MINISETUP_URL, MiniSetupFileNameNPath, true))
|
||||
{
|
||||
// * Important * sanity check. Kumar/Jeff found this. State can happen that we can reach the
|
||||
// version url but don't actually download the file which then causes the service to crash when
|
||||
// calling PSetupSpwan (might as well also make sure that the new file is equal to the file we expect)
|
||||
if (File.Exists(MiniSetupFileNameNPath))
|
||||
{
|
||||
// The Setup will also try to auto-close this service, so first update the dt then spawn the setup.exe
|
||||
SetLastUpdated(DateTime.Now);
|
||||
PlutoService.AppLogInfo(String.Format("Updating to newer Mobile Api Service '{0}' via '{1}'", OnlineVersion.ToString(), MiniSetupFileNameNPath));
|
||||
|
||||
//No longer needed - ServiceStartVersionSent (handled in PlutoService.MSL.cs) will take care of this for us
|
||||
//RegistrationWrapper.ServerHasBeenUpdated(OnlineVersion.ToString());
|
||||
|
||||
// The auto-update is also forcing a close (however we will also try to committ suicide)
|
||||
Yaulw.Installer.Common.PSetupSpwan(MiniSetupFileNameNPath, "", false);
|
||||
|
||||
// * Double Knock-out * Force the Service to close here a kill itself here as well, don't know if this even get's called
|
||||
// but might as well make sure and double punch
|
||||
//PlutoService.StopNow();
|
||||
//PlutoService.KillCurrentProccess();
|
||||
}
|
||||
else
|
||||
{
|
||||
PlutoService.AppLogInfo(String.Format("Failed to download the file to update the service, please download and install manually: '{0}'", Configuration.DOWNLOAD_MINISETUP_URL));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launch the Update within a Thread() with specified Delay,
|
||||
/// Thread only launched if Delay > 0, otherwise just calls CheckForUpdatesAndUpdate() directly
|
||||
/// </summary>
|
||||
/// <param name="nDelay"></param>
|
||||
internal static void LaunchUpdateThread(int nDelayInSeconds)
|
||||
{
|
||||
if (nDelayInSeconds > 0)
|
||||
{
|
||||
UpdateThreadParams p = new UpdateThreadParams() { nDelay = (int)TimeSpan.FromSeconds(nDelayInSeconds).TotalMilliseconds };
|
||||
Yaulw.Thread.TStarter.StartParameterizedThread(CheckForUpdatesAndUpdate, p, "CheckForUpdate_Thread", System.Threading.ApartmentState.MTA, true, System.Threading.ThreadPriority.Normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckForUpdatesAndUpdate(null);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user