diff --git a/.gitignore b/.gitignore index a0c4a6ec..cd820889 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ /Deheader/obj /Deheader/obj/Debug /Deheader/obj/Release +/RombaSharp/obj +/RombaSharp/obj/Debug +/RombaSharp/obj/Release /SabreTools/obj /SabreTools/obj/Debug /SabreTools/obj/Release @@ -18,3 +21,5 @@ /SimpleSort/obj/Debug /SimpleSort/obj/Release /TGZConvert/obj +/TGZConvert/obj/Debug +/TGZConvert/obj/Release \ No newline at end of file diff --git a/RombaSharp/App.config b/RombaSharp/App.config new file mode 100644 index 00000000..88fa4027 --- /dev/null +++ b/RombaSharp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/RombaSharp/Properties/AssemblyInfo.cs b/RombaSharp/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..56140875 --- /dev/null +++ b/RombaSharp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RombaSharp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RombaSharp")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4728d479-8cfb-43e9-8c63-4774c6d73200")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/RombaSharp/RombaSharp.cs b/RombaSharp/RombaSharp.cs new file mode 100644 index 00000000..bbd18d03 --- /dev/null +++ b/RombaSharp/RombaSharp.cs @@ -0,0 +1,394 @@ +using Mono.Data.Sqlite; +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using SabreTools.Helper; + +namespace SabreTools +{ + /// + /// Entry class for the RombaSharp application + /// + public class RombaSharp + { + // General settings + private int _workers; //Number of parallel threads + private string _logdir; //Log folder location + private string _tmpdir; //Temp folder location + private string _webdir; // Web frontend location + private string _baddir; // Fail-to-unpack file folder location + private int _verbosity; // Verbosity of the output + private int _cores; // Forced CPU cores + + // DatRoot settings + private string _dats; // DatRoot folder location + private string _db; // Database name + + // Depot settings + private Dictionary> _depots; // Folder location, Max size + + // Server settings + private int _port; // Web server port + + // Other private variables + private string _config = "config.xml"; + private string _connectionString; + private Logger _logger; + + /// + /// Create a new RombaSharp object + /// + /// Logger object for file and console output + public RombaSharp(Logger logger) + { + _logger = logger; + + InitializeConfiguration(); + InitializeDatabase(); + } + + public static void Main(string[] args) + { + } + + /// + /// Initialize the Romba application from XML config + /// + private void InitializeConfiguration() + { + // Get default values if they're not written + int workers = 4, + verbosity = 1, + cores = 4, + port = 4003; + string logdir = "logs", + tmpdir = "tmp", + webdir = "web", + baddir = "bad", + dats = "dats", + db = "db", + connectionString = ""; + Dictionary> depots = new Dictionary>(); + + // Get the XML text reader for the configuration file, if possible + XmlTextReader xtr = DatTools.GetXmlTextReader(_config, _logger); + + /* XML file structure + + + + 4 + logs + tmp + web + bad + 1 + 4 + + + dats + db + + + + depot + 40000 + true + + + + 4003 + + + + */ + + // Now parse the XML file for settings + if (xtr != null) + { + xtr.MoveToContent(); + while (!xtr.EOF) + { + // We only want elements + if (xtr.NodeType != XmlNodeType.Element) + { + xtr.Read(); + continue; + } + + switch (xtr.Name) + { + case "workers": + workers = xtr.ReadElementContentAsInt(); + break; + case "logdir": + logdir = xtr.ReadElementContentAsString(); + break; + case "tmpdir": + tmpdir = xtr.ReadElementContentAsString(); + break; + case "webdir": + webdir = xtr.ReadElementContentAsString(); + break; + case "baddir": + baddir = xtr.ReadElementContentAsString(); + break; + case "verbosity": + verbosity = xtr.ReadElementContentAsInt(); + break; + case "cores": + cores = xtr.ReadElementContentAsInt(); + break; + case "dats": + dats = xtr.ReadElementContentAsString(); + break; + case "db": + db = xtr.ReadElementContentAsString(); + break; + case "depot": + XmlReader subreader = xtr.ReadSubtree(); + if (subreader != null) + { + string root = ""; + long maxsize = -1; + bool online = true; + + while (!subreader.EOF) + { + // We only want elements + if (subreader.NodeType != XmlNodeType.Element) + { + subreader.Read(); + continue; + } + + switch (subreader.Name) + { + case "root": + root = subreader.ReadElementContentAsString(); + break; + case "maxsize": + maxsize = subreader.ReadElementContentAsLong(); + break; + case "online": + online = subreader.ReadElementContentAsBoolean(); + break; + default: + subreader.Read(); + break; + } + } + + try + { + depots.Add(root, new Tuple(maxsize, online)); + } + catch + { + // Ignore add errors + } + } + + xtr.Skip(); + break; + case "port": + port = xtr.ReadElementContentAsInt(); + break; + default: + xtr.Read(); + break; + } + } + } + + // Now validate the values given + if (workers < 1) + { + workers = 1; + } + if (workers > 8) + { + workers = 8; + } + if (!Directory.Exists(logdir)) + { + Directory.CreateDirectory(logdir); + } + if (!Directory.Exists(tmpdir)) + { + Directory.CreateDirectory(tmpdir); + } + if (!Directory.Exists(webdir)) + { + Directory.CreateDirectory(webdir); + } + if (!Directory.Exists(baddir)) + { + Directory.CreateDirectory(baddir); + } + if (verbosity < 0) + { + verbosity = 0; + } + if (verbosity > 3) + { + verbosity = 3; + } + if (cores < 1) + { + cores = 1; + } + if (cores > 16) + { + cores = 16; + } + if (!Directory.Exists(dats)) + { + Directory.CreateDirectory(dats); + } + db = Path.GetFileNameWithoutExtension(db) + ".sqlite"; + connectionString = "Data Source=" + _db + ";Version = 3;"; + foreach (string key in depots.Keys) + { + if (!Directory.Exists(key)) + { + Directory.CreateDirectory(key); + } + } + if (port < 0) + { + port = 0; + } + if (port > 65535) + { + port = 65535; + } + + // Finally set all of the fields + _workers = workers; + _logdir = logdir; + _tmpdir = tmpdir; + _webdir = webdir; + _baddir = baddir; + _verbosity = verbosity; + _cores = cores; + _dats = dats; + _db = db; + _connectionString = connectionString; + _depots = depots; + _port = port; + } + + /// + /// Initialize the Romba database + /// + private void InitializeDatabase() + { + // Make sure the db is set + if (String.IsNullOrEmpty(_db)) + { + _db = "db.sqlite"; + _connectionString = "Data Source=" + _db + ";Version = 3;"; + } + + // Make sure the file exists + if (!File.Exists(_db)) + { + SqliteConnection.CreateFile(_db); + } + + // Connect to the file + SqliteConnection dbc = new SqliteConnection(_connectionString); + dbc.Open(); + + // Initialize the database schema + try + { + string query = @" +CREATE TABLE IF NOT EXISTS data ( +'id' INTEGER NOT NULL +'key' TEXT NOT NULL +'value' TEXT NOT NULL +)"; + SqliteCommand slc = new SqliteCommand(query, dbc); + slc.ExecuteNonQuery(); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + finally + { + // Close the database connection + dbc.Close(); + } + } + + /// + /// Populate or refresh the database information + /// + private void RefreshDatabase() + { + // Make sure the dats dir is set + if (String.IsNullOrEmpty(_dats)) + { + _dats = "dats"; + } + + // Make sure the folder exists + if (!Directory.Exists(_dats)) + { + Directory.CreateDirectory(_dats); + } + + // Now parse the directory into an internal Dat then insert + foreach (string file in Directory.EnumerateFiles(_dats, "*", SearchOption.AllDirectories)) + { + Dat datdata = new Dat(); + datdata = DatTools.Parse(file, 0, 0, datdata, _logger); + Rom romdata = FileTools.GetSingleFileInfo(file); + } + } + + /// + /// Process a datfile and insert it into the database + /// + /// Dat object representing the data to insert + /// Rom object representing the Dat file itself + private void InsertDatIntoDatabase(Dat datdata, Rom romdata) + { + // Make sure the db is set + if (String.IsNullOrEmpty(_db)) + { + _db = "db.sqlite"; + _connectionString = "Data Source=" + _db + ";Version = 3;"; + } + + // Make sure the file exists + if (!File.Exists(_db)) + { + SqliteConnection.CreateFile(_db); + InitializeDatabase(); + } + + // Open a connection to the database + using (SqliteConnection slc = new SqliteConnection(_connectionString)) + { + // For each key + foreach (string key in datdata.Files.Keys) + { + // For each Rom in the list + foreach (Rom file in datdata.Files[key]) + { + // Try to find the hash in the set + + // If it exists, see if there's any missing information + + // If it doesn't exist, insert it completely + } + } + } + } + } +} diff --git a/RombaSharp/RombaSharp.csproj b/RombaSharp/RombaSharp.csproj new file mode 100644 index 00000000..1c368c5a --- /dev/null +++ b/RombaSharp/RombaSharp.csproj @@ -0,0 +1,85 @@ + + + + + Debug + AnyCPU + {4728D479-8CFB-43E9-8C63-4774C6D73200} + Exe + Properties + RombaSharp + RombaSharp + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Mono.Data.Sqlite.Portable.1.0.3.5\lib\net4\Mono.Data.Sqlite.dll + True + + + + + ..\packages\Mono.Data.Sqlite.Portable.1.0.3.5\lib\net4\System.Data.Portable.dll + True + + + + ..\packages\Mono.Data.Sqlite.Portable.1.0.3.5\lib\net4\System.Transactions.Portable.dll + True + + + + + + + + + + + + + + + + + + + {225a1afd-0890-44e8-b779-7502665c23a5} + SabreTools.Helper + + + + + + + + + + \ No newline at end of file diff --git a/RombaSharp/packages.config b/RombaSharp/packages.config new file mode 100644 index 00000000..2e7f170d --- /dev/null +++ b/RombaSharp/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/SabreTools.sln b/SabreTools.sln index b24c79ac..c77221a3 100644 --- a/SabreTools.sln +++ b/SabreTools.sln @@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleSort", "SimpleSort\Si EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGZConvert", "TGZConvert\TGZConvert.csproj", "{73FBE2C1-39FB-4FFC-93F4-FB4998492429}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RombaSharp", "RombaSharp\RombaSharp.csproj", "{4728D479-8CFB-43E9-8C63-4774C6D73200}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -68,6 +70,14 @@ Global {73FBE2C1-39FB-4FFC-93F4-FB4998492429}.Release|Any CPU.Build.0 = Release|Any CPU {73FBE2C1-39FB-4FFC-93F4-FB4998492429}.Release|x64.ActiveCfg = Release|Any CPU {73FBE2C1-39FB-4FFC-93F4-FB4998492429}.Release|x64.Build.0 = Release|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|x64.ActiveCfg = Debug|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|x64.Build.0 = Debug|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|Any CPU.Build.0 = Release|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|x64.ActiveCfg = Release|Any CPU + {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE