All pastes #952201 Raw Edit

Something

public text v1 · immutable
#952201 ·published 2008-03-21 23:37 UTC
rendered paste body
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Data;
using System.Threading;
using System.Text.RegularExpressions;

namespace Bookings_And_Loans.Database
{
    /// <summary>
    /// This file will handle the backup aspect of the system
    /// </summary>
    class csBackupSystem
    {
        //Declare the variables I will be using within this file
        private static bool isJournalEnabled = true;
        private static string backupLocation_;
        public static string backupLocation
        {
            //When accessed, return the value of backupLocation_
            get { return backupLocation_; }
            set
            {
                //When attempting to set the value of this variable, move all existing backups to the new folder
                if (backupLocation_!= null) { MoveAllExistingBackups(backupLocation_, value); }
                //Set the journal file to the new location
                journalFile = value + "\\journal.txt";
                //Save the settings
                Properties.Settings.Default.BackupLocation = value;
                Properties.Settings.Default.Save();
                backupLocation_ = value;
            }
        }
        private static string journalFile;

        public static void Initialize()
        {
            //A method to start all aspects directly related to the backups system
            backupLocation = Properties.Settings.Default.BackupLocation;
            if (!Directory.Exists(backupLocation))
            { Directory.CreateDirectory(backupLocation); }
            //Add the eventhandlers for each of the tables to be covered by the backup system
            for (int repeat = 0; repeat < csDatabase.dbBookings.Tables.Count; repeat++)
            {
                csDatabase.dbBookings.Tables[repeat].RowChanged += new System.Data.DataRowChangeEventHandler(csBackupSystem_RowChanged);
                csDatabase.dbBookings.Tables[repeat].RowDeleting += new System.Data.DataRowChangeEventHandler(csBackupSystem_RowChanged);
                csDatabase.dbBookings.Tables[repeat].TableCleared += new DataTableClearEventHandler(csBackupSystem_TableCleared);
            }
            //Call the procedure which will check if a new backup is required
            CheckBackup();
        }

        static void csBackupSystem_TableCleared(object sender, DataTableClearEventArgs e)
        {
            //Create a string to reflect that a table was cleared within the database
            string lineToLog;
            lineToLog = e.Table.TableName + "><" + "Clear" + "><" + "%%";
            LogChange(lineToLog);
        }

        private static void CheckBackup()
        {
            //Start a new thread, to avoid making the program unresponsive while checking/backing up
            new Thread(delegate()
            {
                //Create an unending loop, which will pause for 12hours after each run through
                while (true)
                {
                    //Get a list of backups and find the latest one
                    string[] backupFolders = Directory.GetDirectories(backupLocation);
                    string latestBackup = DateTime.Today.AddDays(-8).ToString("yyyy-MM-dd");
                    if (backupFolders.Length > 0)
                    { latestBackup = backupFolders[backupFolders.Length - 1].Split('\\')[backupFolders[backupFolders.Length - 1].Split('\\').Length-1]; }

                    DateTime dateOfLastBackup = DateTime.Parse(latestBackup);
                    //Compare todays date to the last backup, and if the last backup was seven days ago, make a new backup
                    if (DateTime.Compare(dateOfLastBackup.AddDays(7), DateTime.Today).Equals(-1))
                    {
                        CreateBackup();
                    }
                    int nextCheckInterval = (((60 * 1000) * 60) * 12);
                    Thread.Sleep(nextCheckInterval);
                }
            }) { IsBackground = true }.Start();
        }

        private static void CreateBackup()
        {
            //Create the directory to backup to and get a list of files to backup
            Directory.CreateDirectory(backupLocation + "\\" + DateTime.Today.ToString("yyyy-MM-dd"));
            string[] filesToBackup = new string[] { "bookings.txt", "loans.txt", "archived_loans,txt", 
                "archived_bookings.txt", "users.xml", "journal.txt" };
            //Foreach file to backup, copy it to the backup folder
            for (int repeat = 0; repeat < filesToBackup.Length; repeat++)
            {
                string fileToCopy = filesToBackup[repeat];
                if (File.Exists(fileToCopy))
                {
                    File.Copy(fileToCopy, backupLocation + "\\" + DateTime.Today.ToString("yyyy-MM-dd") + "\\" + fileToCopy);
                }
            }
            //Delete the journal file as all recorded data is no longer needed
            File.Delete(journalFile);  
        }

        private static void csBackupSystem_RowChanged(object sender, System.Data.DataRowChangeEventArgs e)
        {
            //If the table being added to is an archive table, set the archive date of the record
            if (e.Action.ToString().Equals("Add") && e.Row.Table.TableName.StartsWith("archived"))
            { e.Row["Date Archived"] = DateTime.Now; }
            string lineToLog;
            //Create the string which is to be recorded, including table, action and all values after the change in the row
            lineToLog = e.Row.Table.TableName + "><" + e.Action + "><";
            for (int repeat = 0; repeat < e.Row.ItemArray.Length; repeat++)
            {
                lineToLog += "%%" + e.Row.ItemArray[repeat];
            }
            //Log the change
            LogChange(lineToLog);
        }

        private static void LogChange(string changeToLog)
        {
            //If the journal file is active, write the change to the database
            if (isJournalEnabled)
            {
                StreamWriter journalWriter = File.AppendText(journalFile);
                journalWriter.WriteLine(changeToLog);
                journalWriter.Flush();
                journalWriter.Close();
            }
        }

        public static void RestoreLastBackup()
        {
            //Find the latest backup and restore it
            string[] backupFolders = Directory.GetDirectories(backupLocation);
            string latestBackup = DateTime.Today.AddDays(-8).ToString("dd-MM-yyyy");
            if (backupFolders.Length > 0)
            { latestBackup = backupFolders[backupFolders.Length - 1].Split('\\')[1]; }
            RestoreBackup(latestBackup);
        }

        public static void RestoreBackup(string folderToUse)
        {
            //Make sure the journal doesn't log the changes made when restoring the backup
            isJournalEnabled = false;
            csDatabase.ClearAllTables();
            string[] filesToRestore = new string[] { "bookings.txt", "loans.txt", "archived_loans,txt", "archived_bookings.txt", "users.xml" };
            for (int repeat = 0; repeat < filesToRestore.Length; repeat++)
            {
                string fileToRestore = filesToRestore[repeat];
                if (File.Exists(backupLocation + "\\" + folderToUse + "\\" + fileToRestore))
                {
                    File.Copy(backupLocation + "\\" + folderToUse + "\\" + fileToRestore, fileToRestore, true);
                    csDatabase.LoadTable(fileToRestore.Split('.')[0]);
                }
            }
            //Restore all changes recorded in the journal
            RestoreJournal();
            isJournalEnabled = true;
        }

        private static void RestoreJournal()
        {
            //If the journal file exists, continue
            if (File.Exists(journalFile))
            {
                StreamReader journalReader = new StreamReader(journalFile);
                string line = "";
                while ((line = journalReader.ReadLine()) != null)
                {
                    try
                    {
                        //Set the variables which will hold the data required by the system to restore each change
                        string tableToAffect = Regex.Split(line, "><")[0];
                        string actionToPerform = Regex.Split(line, "><")[1];
                        string[] fieldValues = Regex.Split(Regex.Split(line, "><")[2], "%%");
                        string idColumn = csDatabase.dbBookings.Tables[tableToAffect].Columns[0].ColumnName;
                        DataRow rowToEdit;
                        
                        switch (actionToPerform)
                        {
                            case "Change":
                                {
                                    rowToEdit = csDatabase.dbBookings.Tables[tableToAffect].Select("[" + idColumn + "] = " + fieldValues[1])[0];
                                    for (int a = 0; a < rowToEdit.Table.Columns.Count; a++)
                                    {
                                        string columnToEdit = rowToEdit.Table.Columns[a].ColumnName;
                                        rowToEdit[columnToEdit] = fieldValues[a + 1];
                                    }
                                    break;
                                }
                            case "Add":
                                {
                                    rowToEdit = csDatabase.dbBookings.Tables[tableToAffect].NewRow();
                                    for (int a = 0; a < rowToEdit.Table.Columns.Count; a++)
                                    {
                                        string columnToEdit = rowToEdit.Table.Columns[a].ColumnName;
                                        string dataTypeOfColumn = rowToEdit.Table.Columns[a].DataType.ToString();
                                        rowToEdit[columnToEdit] = fieldValues[a + 1];
                                    }
                                    csDatabase.dbBookings.Tables[tableToAffect].Rows.Add(rowToEdit);
                                    break;
                                }
                            case "Delete":
                                {
                                    rowToEdit = csDatabase.dbBookings.Tables[tableToAffect].Select("[" + idColumn + "] = " + fieldValues[1])[0];
                                    csDatabase.dbBookings.Tables[tableToAffect].Rows.Remove(rowToEdit);
                                    break;
                                }
                            case "Clear":
                                {
                                    csDatabase.dbBookings.Tables[tableToAffect].Clear();
                                    break;
                                }
                        }
                    }
                    catch (Exception e) { }
                }
            }
        }

        private static void MoveAllExistingBackups(string existingFolder, string newFolder)
        {
            //Get a list of existing backups
            string[] backupFolders = Directory.GetDirectories(existingFolder);
            if (File.Exists(existingFolder + "\\journal.txt")) { File.Copy(existingFolder + "\\journal.txt", newFolder + "\\journal.txt"); }
            //For each existing backup
            for (int repeat = 0; repeat < backupFolders.Length; repeat++)
            {
                //Get a list of files and move them to the relevant new directory
                string[] backupFiles = Directory.GetFiles(backupFolders[repeat]);
                string folderName = Regex.Split(backupFolders[repeat], "\\\\")[Regex.Split(backupFolders[repeat], "\\\\").Length - 1];
                Directory.CreateDirectory(newFolder + "\\" + folderName);
                for (int repeat_ = 0; repeat_ < backupFiles.Length; repeat_++)
                {
                     string destination = newFolder + "\\" + Regex.Match(backupFiles[repeat_], "([0-9]*(-)?){3}\\\\[a-z]*\\.[a-z]{3}").Value;
                     File.Copy(backupFiles[repeat_], destination);
                     File.Delete(backupFiles[repeat_]);
                }
                //Delete the existing backup
                Directory.Delete(backupFolders[repeat]);
            }
        }
    }
}