Initial Commit

This commit is contained in:
2016-07-27 00:32:34 -04:00
commit 8d162b2035
701 changed files with 188672 additions and 0 deletions

View 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
}
}