[chronojump/update-database-before-importing] When importing a chronojump database: updates it to the current version before calling the importing



commit 2fb36d0615b0a103a5450bcf2f99a8ddfe867c5e
Author: Carles Pina i Estany <carles pina cat>
Date:   Fri Sep 30 12:05:12 2016 +0200

    When importing a chronojump database: updates it to the current version before calling the importing code.
    
    Adds a new class: StaticClassState. This class saves all the static
    variables of a given class into a dictionary (see its documentation).
    
    Because we have static data for Sqlite class what happens here:
    a) it saves Sqlite class data
    b) it uses Sqlite class to Convert the importing database to the current
    version
    c) it restores the Sqlite previous state
    
    Instead of doing this we could avoid having all the static data but this
    is a major refactoring that needs to be done in another moment (and
    quite a risky refactoring).

 chronojump.csproj         |    1 +
 src/Makefile.am           |    1 +
 src/chronojump.cs         |    6 +++-
 src/chronojumpImporter.cs |   41 ++++++++++++++++++++++++-
 src/sqlite/main.cs        |   24 +++++++++++++++
 src/staticClassState.cs   |   73 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 144 insertions(+), 2 deletions(-)
---
diff --git a/chronojump.csproj b/chronojump.csproj
index d04d7a8..acc3e57 100644
--- a/chronojump.csproj
+++ b/chronojump.csproj
@@ -879,6 +879,7 @@
     <Compile Include="src\chronopicRegister.cs" />
     <Compile Include="src\sqlite\chronopicRegister.cs" />
     <Compile Include="src\chronojumpImporter.cs" />
+    <Compile Include="src\staticClassState.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="src\" />
diff --git a/src/Makefile.am b/src/Makefile.am
index 0054c01..175960c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -176,6 +176,7 @@ SOURCES = \
        serverPing.cs\
        serverEvaluator.cs\
        server.cs\
+       staticClassState.cs\
        chronopic.cs\
        chronopicDetect.cs\
        chronopicRegister.cs\
diff --git a/src/chronojump.cs b/src/chronojump.cs
index 05a45cb..0337efc 100644
--- a/src/chronojump.cs
+++ b/src/chronojump.cs
@@ -474,7 +474,11 @@ public class ChronoJump
                SqlitePreferences.Update("simulated", "True", true); //dbcon opened
 
                Sqlite.Close();
-               
+
+               // Chronojump sqlite is in an initialized state, let's keep the Sqlite state here
+               // to be re-used
+               Sqlite.saveClassState ();
+
                allSQLCallsDoneOnSqliteThingsThread = true;
                LogB.SQL("all SQL calls done on sqliteThings thread");
                
diff --git a/src/chronojumpImporter.cs b/src/chronojumpImporter.cs
index c3f54ab..af90334 100644
--- a/src/chronojumpImporter.cs
+++ b/src/chronojumpImporter.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic; //List
 using System.Json;
 using System.Diagnostics;
 using System;
+using System.IO;
 using Mono.Unix;
 
 /*
@@ -28,10 +29,18 @@ using Mono.Unix;
 
 class ChronojumpImporter
 {
+       // Database that it's importing from
        private string sourceFile;
+
+       // Database that it's importing to (usually chronojump.db database)
        private string destinationFile;
+
+       // Session that will import
        private string session;
 
+       // When importing we might copy the sourceFile to update to the current database.
+       // The file is deleted afterwards
+       private string temporaryFile = "";
 
        // Result struct holds the output, error and success operations. It's used to pass
        // errors from different layers (e.g. executing Python scripts) to the UI layer
@@ -74,11 +83,17 @@ class ChronojumpImporter
                if (! destinationDatabaseVersion.success)
                        return destinationDatabaseVersion;
 
-               if (float.Parse(destinationDatabaseVersion.output) < 
float.Parse(sourceDatabaseVersion.output)) {
+               float destinationDatabaseVersionNum = float.Parse (destinationDatabaseVersion.output);
+               float sourceDatabaseVersionNum = float.Parse (sourceDatabaseVersion.output);
+
+               if (destinationDatabaseVersionNum < sourceDatabaseVersionNum) {
                        return new Result (false, Catalog.GetString ("Trying to import a newer database 
version than this Chronojump\n" +
                                "Please, update the running Chronojump."));
+               } else if (destinationDatabaseVersionNum > sourceDatabaseVersionNum) {
+                       updateSourceDatabase ();
                }
 
+
                List<string> parameters = new List<string> ();
                parameters.Add ("--source");
                parameters.Add (CommandLineEncoder.EncodeArgText (sourceFile));
@@ -89,9 +104,33 @@ class ChronojumpImporter
 
                Result result = executeChronojumpImporter (parameters);
 
+               if (temporaryFile != "") {
+                       File.Delete (temporaryFile);
+                       temporaryFile = "";
+               }
+
                return result;
        }
 
+       private bool updateSourceDatabase()
+       {
+               StaticClassState classOriginalState = new StaticClassState (typeof (Sqlite));
+               temporaryFile = Path.GetTempFileName ();
+
+               File.Copy (sourceFile, temporaryFile, true);
+
+               classOriginalState.readAttributes ();
+
+               classOriginalState.writeAttributes (Sqlite.InitialState);
+               Sqlite.setSqlFilePath (temporaryFile);
+               Sqlite.ConvertToLastChronojumpDBVersion ();
+
+               classOriginalState.writeAttributes (classOriginalState);
+               Sqlite.Connect ();
+
+               return true;
+       }
+
        private Result getSourceDatabaseVersion()
        {
                return getDatabaseVersionFromFile (sourceFile);
diff --git a/src/sqlite/main.cs b/src/sqlite/main.cs
index aa89445..8c278f5 100644
--- a/src/sqlite/main.cs
+++ b/src/sqlite/main.cs
@@ -116,6 +116,10 @@ class Sqlite
        public static bool IsOpened = false;
        public static bool SafeClose = true;
 
+       // Here it saves the initial class state before it's used. So we can restore it any time
+       // if needed
+       private static StaticClassState initialState;
+
        /*
         * Important, change this if there's any update to database
         */
@@ -285,6 +289,26 @@ class Sqlite
                }
        }
 
+       public static void setSqlFilePath(string filePath)
+       {
+               sqlFile = filePath;
+               connectionString = "version = 3; Data source = " + sqlFile;
+       }
+
+       public static void saveClassState()
+       {
+               initialState = new StaticClassState (typeof (Sqlite));
+               initialState.readAttributes ();
+       }
+
+       public static StaticClassState InitialState
+       {
+               get
+               {
+                       return initialState;
+               }
+       }
+
        //only create blank DB
        public static void ConnectBlank()
        {
diff --git a/src/staticClassState.cs b/src/staticClassState.cs
new file mode 100644
index 0000000..6c8a070
--- /dev/null
+++ b/src/staticClassState.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Reflection;
+using System.Collections;
+
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or   
+ * (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Copyright (C) 2016   Carles Pina i Estany <carles pina cat>
+ */
+
+
+// This class reads and writes static class states. Reads all the attributes and keeps them,
+// then the static class can be changed but the original attributes can be re-written again
+// to go back to the previous state.
+class StaticClassState
+{
+       private Hashtable attributes;
+       private Type classType;
+
+       public StaticClassState(Type classType)
+       {
+               // call new StaticClassState(typeof (class));
+               this.classType = classType;
+       }
+
+       // Reads all the static attributes of this class and saves them into a dictionary (to be used in the 
writeAttributes)
+       public void readAttributes()
+       {
+               attributes = new Hashtable ();
+
+               foreach (var field in classType.GetFields(System.Reflection.BindingFlags.Static | 
System.Reflection.BindingFlags.NonPublic))
+               {
+                       string name = field.Name;
+                       var value = field.GetValue(null); // static classes cannot be instanced, so use 
null...
+                       attributes.Add (name, value);
+               }
+       }
+
+       // Writes the read attributes back into the class. See readAttributes()
+       public void writeAttributes()
+       {
+               writeAttributesDo (this);
+       }
+
+       // Writes the attributes from staticClassState parameter into the existing class (defined in the 
constructor)
+       public void writeAttributes(StaticClassState staticClassState)
+       {
+               writeAttributesDo (staticClassState);
+       }
+
+       private void writeAttributesDo(StaticClassState staticClassState)
+       {
+               foreach (var field in classType.GetFields(System.Reflection.BindingFlags.Static | 
System.Reflection.BindingFlags.NonPublic))
+               {
+                       string name = field.Name;
+                       field.SetValue (name, attributes [name]);
+               }
+       }
+}
\ No newline at end of file


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]