/// <summary> /// see if any patches are missing; is there a direct line between FCurrentlyInstalledVersion and FLatestAvailablePatch? /// </summary> /// <returns>return a list of all patches that should be applied. empty list if there is a problem</returns> public SortedList CheckPatchesConsistent(SortedList AOrderedListOfAllPatches) { SortedList ResultPatchList = new SortedList(); TFileVersionInfo testPatchVersion; // get the latest patch that is available FLatestAvailablePatch = new TFileVersionInfo(FCurrentlyInstalledVersion); foreach (string patch in AOrderedListOfAllPatches.GetValueList()) { testPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(patch); if (testPatchVersion.Compare(FLatestAvailablePatch) > 0) { FLatestAvailablePatch = testPatchVersion; } } // drop unnecessary patch files // ie. patch files leading to the same version, eg. 2.2.11-1 and 2.2.12-2 to 2.2.12-3 // we only want the biggest step testPatchVersion = new TFileVersionInfo(FCurrentlyInstalledVersion); bool patchesAvailable = true; while (patchesAvailable) { StringCollection applyingPatches = new StringCollection(); foreach (string patch in AOrderedListOfAllPatches.GetValueList()) { if (TPatchFileVersionInfo.PatchApplies(testPatchVersion, patch)) { applyingPatches.Add(patch); } } patchesAvailable = (applyingPatches.Count > 0); if (applyingPatches.Count > 0) { // see which of the applying patches takes us further string highestPatch = applyingPatches[0]; TFileVersionInfo highestPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(highestPatch); foreach (string patch in applyingPatches) { if (TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(patch).Compare(highestPatchVersion) > 0) { highestPatch = patch; highestPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(highestPatch); } } ResultPatchList.Add(highestPatch, highestPatch); testPatchVersion = highestPatchVersion; } } if (FLatestAvailablePatch.Compare(testPatchVersion) != 0) { // check for a generic patch file, starting from version 0.0.99.99 foreach (string patch in AOrderedListOfAllPatches.GetValueList()) { if (patch.Contains("0.0.99.99")) { testPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(patch); ResultPatchList.Clear(); ResultPatchList.Add(patch, patch); } } } if (FLatestAvailablePatch.Compare(testPatchVersion) != 0) { TLogging.Log("missing patchfile from version " + testPatchVersion.ToString() + " to " + FLatestAvailablePatch.ToString()); return new SortedList(); } return ResultPatchList; }
/// <summary> /// apply one single database patch. /// if this is the last patch, an email could be sent, etc /// </summary> /// <param name="ADesiredVersion"></param> /// <param name="ALastPatch"></param> /// <returns></returns> private Boolean RunDBPatch(TFileVersionInfo ADesiredVersion, Boolean ALastPatch) { TDBTransaction WriteTransaction = null; bool SubmissionResult = false; // TODO: run sql script or code from DLL to update the database // TODO: if last patch, send an email to central support etc TLogging.Log("RunDBPatch " + ADesiredVersion.ToString()); // find appropriate sql script that updates to this version string[] files = Directory.GetFiles(FPatchesPath, String.Format("*_{0}.{1}.{2}.sql", ADesiredVersion.FileMajorPart, ADesiredVersion.FileMinorPart, ADesiredVersion.FileBuildPart)); if (files.Length > 1) { throw new Exception("There are too many files for upgrading to version " + ADesiredVersion.ToString() + " in " + FPatchesPath); } if (files.Length == 0) { throw new Exception("We cannot find a file for upgrading to version " + ADesiredVersion.ToString() + " in " + FPatchesPath); } TLogging.Log("Applying " + Path.GetFileName(files[0])); DBAccess.GDBAccessObj.BeginAutoTransaction(IsolationLevel.Serializable, ref WriteTransaction, ref SubmissionResult, delegate { // always upgrade the version number DBAccess.GDBAccessObj.ExecuteNonQuery( String.Format( "UPDATE s_system_defaults SET s_default_value_c = '{0}.{1}.{2}-0' WHERE s_default_code_c='CurrentDatabaseVersion'", ADesiredVersion.FileMajorPart, ADesiredVersion.FileMinorPart, ADesiredVersion.FileBuildPart), WriteTransaction); StreamReader reader = new StreamReader(files[0]); string line; string stmt = string.Empty; while ((line = reader.ReadLine()) != null) { if (!line.Trim().StartsWith("--")) { if (!line.Trim().EndsWith(";")) { stmt += line.Trim() + " "; } else { stmt += line.Trim(); DBAccess.GDBAccessObj.ExecuteNonQuery(stmt, WriteTransaction); } } if (stmt.Length > 0) { DBAccess.GDBAccessObj.ExecuteNonQuery(stmt, WriteTransaction); } } SubmissionResult = true; }); return true; }
/// <summary> /// Import all data of a partner from a text file, using a format used by Petra 2.x. /// Containing: partner, person/family/church/etc record, valid locations, contact details, special types, /// interests, personnel data, commitments, applications, etc. /// For UNITs there is more specific data, used eg. for the events file. /// </summary> /// <param name="ALinesToImport"></param> /// <param name="ALimitToOption">if this is not an empty string, only the applications for this conference will be imported, historic applications will be ignored</param> /// <param name="ADoNotOverwrite">do not modify records that already exist in the database</param> /// <param name="AResultList">verification results. can contain critical errors and messages for the user</param> /// <returns>nothing - an empty TDS</returns> public PartnerImportExportTDS ImportAllData(string[] ALinesToImport, string ALimitToOption, bool ADoNotOverwrite, out TVerificationResultCollection AResultList) { FResultList = new TVerificationResultCollection(); FCountLocationKeys = -1; FLimitToOption = ALimitToOption; FDoNotOverwrite = ADoNotOverwrite; FMainDS = new PartnerImportExportTDS(); InitReading(ALinesToImport); TFileVersionInfo PetraVersion = new TFileVersionInfo(ReadString()); ReadInt64(); // SiteKey ReadInt32(); // SubVersion if ((PetraVersion.FileMajorPart < 3) && (PetraVersion.FileMinorPart < 2)) { AddVerificationResult( "EXT import not supported from old file type: " + PetraVersion.ToString(), TResultSeverity.Resv_Critical); } else { TDBTransaction Transaction = null; bool SubmissionOK = false; DBAccess.GDBAccessObj.GetNewOrExistingAutoTransaction(IsolationLevel.Serializable, ref Transaction, ref SubmissionOK, delegate { try { while (CheckForKeyword("PARTNER")) { PPartnerRow PartnerRow = ImportPartner(Transaction); ImportPartnerClassSpecific(PartnerRow.PartnerClass, PetraVersion, Transaction); ImportLocation(Transaction); ImportOptionalDetails(PartnerRow, PetraVersion, Transaction); } ImportContext = "Checking data references"; CheckRequiredUnits(Transaction); // AddRequiredUnits(FRequiredOfficeKeys, "F", 1000000, "Office", Transaction); // AddRequiredUnits(FRequiredOptionKeys, "CONF", 1000000, "Conference", Transaction); if (FParsingOfPartnerLocationsForContactDetailsNecessary) { TPartnerContactDetails_LocationConversionHelper.PartnerAttributeLoadUsingTemplate = PPartnerAttributeAccess.LoadUsingTemplate; TPartnerContactDetails_LocationConversionHelper.SequenceGetter = MCommon.WebConnectors.TSequenceWebConnector.GetNextSequence; TPartnerContactDetails_LocationConversionHelper.ParsePartnerLocationsForContactDetails(FMainDS, Transaction); } } catch (Exception e) { TLogging.Log(e.GetType().ToString() + ": " + e.Message + " in line " + (CurrentLineCounter + 1).ToString()); TLogging.Log(CurrentLine); TLogging.Log(e.StackTrace); throw; } SubmissionOK = true; }); } AResultList = FResultList; if (!TVerificationHelper.IsNullOrOnlyNonCritical(AResultList)) { return new PartnerImportExportTDS(); } return FMainDS; }
public static bool ResetDatabase(string AZippedNewDatabaseData) { List <string>tables = TTableList.GetDBNames(); TProgressTracker.InitProgressTracker(DomainManager.GClientID.ToString(), Catalog.GetString("Importing database"), tables.Count + 3); TDBTransaction Transaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.Serializable); try { tables.Reverse(); TProgressTracker.SetCurrentState(DomainManager.GClientID.ToString(), Catalog.GetString("deleting current data"), 0); foreach (string table in tables) { DBAccess.GDBAccessObj.ExecuteNonQuery("DELETE FROM pub_" + table, Transaction); } if (TProgressTracker.GetCurrentState(DomainManager.GClientID.ToString()).CancelJob == true) { TProgressTracker.FinishJob(DomainManager.GClientID.ToString()); DBAccess.GDBAccessObj.RollbackTransaction(); return false; } TSimpleYmlParser ymlParser = new TSimpleYmlParser(PackTools.UnzipString(AZippedNewDatabaseData)); ymlParser.ParseCaptions(); tables.Reverse(); TProgressTracker.SetCurrentState(DomainManager.GClientID.ToString(), Catalog.GetString("loading initial tables"), 1); // one transaction to import the user table and user permissions. otherwise logging in will not be possible if other import fails? bool success = true; success = success && LoadTable("s_user", ymlParser, Transaction); success = success && LoadTable("s_module", ymlParser, Transaction); success = success && LoadTable("s_user_module_access_permission", ymlParser, Transaction); success = success && LoadTable("s_system_defaults", ymlParser, Transaction); success = success && LoadTable("s_system_status", ymlParser, Transaction); // make sure we have the correct database version TFileVersionInfo serverExeInfo = new TFileVersionInfo(TSrvSetting.ApplicationVersion); DBAccess.GDBAccessObj.ExecuteNonQuery(String.Format( "UPDATE PUB_s_system_defaults SET s_default_value_c = '{0}' WHERE s_default_code_c = 'CurrentDatabaseVersion'", serverExeInfo.ToString()), Transaction); if (!success) { DBAccess.GDBAccessObj.RollbackTransaction(); return false; } if (TProgressTracker.GetCurrentState(DomainManager.GClientID.ToString()).CancelJob == true) { TProgressTracker.FinishJob(DomainManager.GClientID.ToString()); DBAccess.GDBAccessObj.RollbackTransaction(); return false; } DBAccess.GDBAccessObj.CommitTransaction(); tables.Remove("s_user"); tables.Remove("s_module"); tables.Remove("s_user_module_access_permission"); tables.Remove("s_system_defaults"); tables.Remove("s_system_status"); FCurrencyPerLedger = new SortedList <int, string>(); Transaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.Serializable); int tableCounter = 2; foreach (string table in tables) { TProgressTracker.SetCurrentState(DomainManager.GClientID.ToString(), String.Format(Catalog.GetString("loading table {0}"), table), tableCounter); tableCounter++; if (TProgressTracker.GetCurrentState(DomainManager.GClientID.ToString()).CancelJob == true) { TProgressTracker.FinishJob(DomainManager.GClientID.ToString()); DBAccess.GDBAccessObj.RollbackTransaction(); return false; } LoadTable(table, ymlParser, Transaction); } TProgressTracker.SetCurrentState(DomainManager.GClientID.ToString(), Catalog.GetString("loading sequences"), tables.Count + 5 + 3); // set sequences appropriately, not lagging behind the imported data foreach (string seq in TTableList.GetDBSequenceNames()) { LoadSequence(seq, ymlParser, Transaction); } TProgressTracker.SetCurrentState(DomainManager.GClientID.ToString(), Catalog.GetString("finish import"), tables.Count + 5 + 4); DBAccess.GDBAccessObj.CommitTransaction(); // reset all cached tables TCacheableTablesManager.GCacheableTablesManager.MarkAllCachedTableNeedsRefreshing(); TProgressTracker.FinishJob(DomainManager.GClientID.ToString()); } catch (Exception e) { TLogging.Log("Problem in ResetDatabase: " + e.Message); TLogging.Log(e.StackTrace); DBAccess.GDBAccessObj.RollbackTransaction(); return false; } return true; }
public static bool ResetDatabase(string AZippedNewDatabaseData) { List <string>tables = TTableList.GetDBNames(); bool SubmissionResult = false; TDBTransaction Transaction = null; string ClientID = "ClientID"; try { ClientID = DomainManager.GClientID.ToString(); } catch (Exception) { } TProgressTracker.InitProgressTracker(ClientID, Catalog.GetString("Restoring Database..."), tables.Count + 3); DBAccess.GDBAccessObj.BeginAutoTransaction(IsolationLevel.Serializable, ref Transaction, ref SubmissionResult, delegate { try { tables.Reverse(); TProgressTracker.SetCurrentState(ClientID, Catalog.GetString("Deleting current data..."), 0); foreach (string table in tables) { DBAccess.GDBAccessObj.ExecuteNonQuery("DELETE FROM pub_" + table, Transaction); } if (TProgressTracker.GetCurrentState(ClientID).CancelJob == true) { TProgressTracker.FinishJob(ClientID); // As SubmissionResult is still false, a DB Transaction Rollback will get // executed automatically and the Method will be exited with return value 'false'! return; } TSimpleYmlParser ymlParser = new TSimpleYmlParser(PackTools.UnzipString(AZippedNewDatabaseData)); ymlParser.ParseCaptions(); tables.Reverse(); TProgressTracker.SetCurrentState(ClientID, Catalog.GetString("Loading initial tables..."), 1); // one transaction to import the user table and user permissions. otherwise logging in will not be possible if other import fails? bool success = true; success = success && LoadTable("s_user", ymlParser, Transaction); success = success && LoadTable("s_module", ymlParser, Transaction); success = success && LoadTable("s_user_module_access_permission", ymlParser, Transaction); success = success && LoadTable("s_system_defaults", ymlParser, Transaction); success = success && LoadTable("s_system_status", ymlParser, Transaction); // make sure we have the correct database version TFileVersionInfo serverExeInfo = new TFileVersionInfo(TSrvSetting.ApplicationVersion); DBAccess.GDBAccessObj.ExecuteNonQuery(String.Format( "UPDATE PUB_s_system_defaults SET s_default_value_c = '{0}' WHERE s_default_code_c = 'CurrentDatabaseVersion'", serverExeInfo.ToString()), Transaction); if (!success) { // As SubmissionResult is still TSubmitChangesResult.scrError, a DB Transaction Rollback will get // executed automatically and the Method will be exited with return value 'false'! return; } if (TProgressTracker.GetCurrentState(ClientID).CancelJob == true) { TProgressTracker.FinishJob(ClientID); // As SubmissionResult is still false, a DB Transaction Rollback will get // executed automatically and the Method will be exited with return value 'false'! return; } tables.Remove("s_user"); tables.Remove("s_module"); tables.Remove("s_user_module_access_permission"); tables.Remove("s_system_defaults"); tables.Remove("s_system_status"); FCurrencyPerLedger = new SortedList <int, string>(); int tableCounter = 2; foreach (string table in tables) { TProgressTracker.SetCurrentState(ClientID, String.Format(Catalog.GetString("Loading Table {0}..."), table), tableCounter); tableCounter++; if (TProgressTracker.GetCurrentState(ClientID).CancelJob == true) { TProgressTracker.FinishJob(ClientID); // As SubmissionResult is still false, a DB Transaction Rollback will get // executed automatically and the Method will be exited with return value 'false'! return; } LoadTable(table, ymlParser, Transaction); } TProgressTracker.SetCurrentState(ClientID, Catalog.GetString("Loading Sequences..."), tables.Count + 5 + 3); // set sequences appropriately, not lagging behind the imported data foreach (string seq in TTableList.GetDBSequenceNames()) { LoadSequence(seq, ymlParser, Transaction); } TProgressTracker.SetCurrentState(ClientID, Catalog.GetString("Finishing Restore..."), tables.Count + 5 + 4); SubmissionResult = true; // reset all cached tables TCacheableTablesManager.GCacheableTablesManager.MarkAllCachedTableNeedsRefreshing(); TProgressTracker.FinishJob(ClientID); } catch (Exception e) { TLogging.Log("Problem in ResetDatabase: " + e.ToString()); TLogging.LogStackTrace(TLoggingType.ToLogfile); throw; } }); return SubmissionResult; }
/// <summary> /// Import all data of a partner from a text file, using a format used by Petra 2.x. /// containing: partner, person/family/church/etc record, valid locations, special types, /// interests, personnel data, commitments, applications /// for units there is more specific data, used eg. for the events file /// </summary> /// <param name="ALinesToImport"></param> /// <param name="ALimitToOption">if this is not an empty string, only the applications for this conference will be imported, historic applications will be ignored</param> /// <param name="ADoNotOverwrite">do not modify records that already exist in the database</param> /// <param name="AResultList">verification results. can contain critical errors and messages for the user</param> /// <returns>nothing - an empty TDS</returns> public PartnerImportExportTDS ImportAllData(string[] ALinesToImport, string ALimitToOption, bool ADoNotOverwrite, out TVerificationResultCollection AResultList) { FResultList = new TVerificationResultCollection(); FCountLocationKeys = -1; FLimitToOption = ALimitToOption; FDoNotOverwrite = ADoNotOverwrite; FMainDS = new PartnerImportExportTDS(); TDBTransaction Transaction; Boolean NewTransaction; InitReading(ALinesToImport); TFileVersionInfo PetraVersion = new TFileVersionInfo(ReadString()); ReadInt64(); // SiteKey ReadInt32(); // SubVersion if ((PetraVersion.FileMajorPart < 3) && (PetraVersion.FileMinorPart < 2)) { AddVerificationResult( "EXT import not supported from old file type: " + PetraVersion.ToString(), TResultSeverity.Resv_Critical); } else { try { Transaction = DBAccess.GDBAccessObj.GetNewOrExistingTransaction(IsolationLevel.Serializable, out NewTransaction); while (CheckForKeyword("PARTNER")) { PPartnerRow PartnerRow = ImportPartner(Transaction); ImportPartnerClassSpecific(PartnerRow.PartnerClass, PetraVersion, Transaction); ImportLocation(Transaction); ImportOptionalDetails(PartnerRow, PetraVersion, Transaction); } ImportContext = "Checking data references"; CheckRequiredUnits(Transaction); // AddRequiredUnits(FRequiredOfficeKeys, "F", 1000000, "Office", Transaction); // AddRequiredUnits(FRequiredOptionKeys, "CONF", 1000000, "Conference", Transaction); } catch (Exception e) { TLogging.Log(e.GetType().ToString() + ": " + e.Message + " in line " + (CurrentLineCounter + 1).ToString()); TLogging.Log(CurrentLine); TLogging.Log(e.StackTrace); throw; } finally { DBAccess.GDBAccessObj.RollbackTransaction(); } } AResultList = FResultList; if (!TVerificationHelper.IsNullOrOnlyNonCritical(AResultList)) { return new PartnerImportExportTDS(); } return FMainDS; }
/// <summary> /// runs all patches against the database; /// can send an email when the last patch has been applied (see RunDBPatch) /// </summary> public Boolean RunDBPatches() { Boolean ReturnValue = false; TFileVersionInfo dbVersion; TFileVersionInfo appVersion; TFileVersionInfo desiredVersion; Boolean lastPatch; DBAccess.GDBAccessObj = new TDataBase(); DBAccess.GDBAccessObj.EstablishDBConnection(CommonTypes.ParseDBType(TAppSettingsManager.GetValue("Server.RDBMSType")), TAppSettingsManager.GetValue("Server.DBHostOrFile"), TAppSettingsManager.GetValue("Server.DBPort"), TAppSettingsManager.GetValue("Server.DBName"), TAppSettingsManager.GetValue("Server.DBUserName"), TAppSettingsManager.GetValue("Server.DBPassword"), ""); dbVersion = GetDBPatchLevel(); dbVersion.FilePrivatePart = 0; TLogging.Log("Current version of the database is " + dbVersion.ToString()); if (dbVersion != null) { ReturnValue = true; StreamReader sr = new StreamReader(FPatchesPath + Path.DirectorySeparatorChar + "version.txt"); appVersion = new TFileVersionInfo(sr.ReadLine()); appVersion.FilePrivatePart = 0; TLogging.Log("We want to update to version " + appVersion.ToString()); sr.Close(); if (dbVersion.Compare(appVersion) == 0) { // rerun the last patch; perhaps the patch file itself was patched ReturnValue = RunDBPatch(dbVersion, true); } for (Int32 Counter = dbVersion.FileBuildPart + 1; Counter <= appVersion.FileBuildPart; Counter += 1) { if (ReturnValue) { desiredVersion = new TFileVersionInfo(dbVersion); desiredVersion.FileBuildPart = (ushort)Counter; lastPatch = (Counter == appVersion.FileBuildPart); ReturnValue = RunDBPatch(desiredVersion, lastPatch); } } } return ReturnValue; }