/// <summary> /// Wrap rescanning depots /// </summary> /// <param name="inputs">List of depots to rescan, empty means all</param> /// TODO: Verify implementation private static void InitRescanDepots(List <string> inputs) { Globals.Logger.Error("This feature is not yet implemented: rescan-depots"); foreach (string depotname in inputs) { // Check that it's a valid depot first if (!_depots.ContainsKey(depotname)) { Globals.Logger.User("'{0}' is not a recognized depot. Please add it to your configuration file and try again", depotname); return; } // Then check that the depot is online if (!Directory.Exists(depotname)) { Globals.Logger.User("'{0}' does not appear to be online. Please check its status and try again", depotname); return; } // Open the database connection SqliteConnection dbc = new SqliteConnection(_connectionString); dbc.Open(); // If we have it, then check for all hashes that are in that depot List <string> hashes = new List <string>(); string query = "SELECT sha1 FROM sha1 WHERE depot=\"" + depotname + "\""; SqliteCommand slc = new SqliteCommand(query, dbc); SqliteDataReader sldr = slc.ExecuteReader(); if (sldr.HasRows) { while (sldr.Read()) { hashes.Add(sldr.GetString(0)); } } // Now rescan the depot itself DatFile depot = new DatFile(); // TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually depot.PopulateFromDir(depotname, Hash.DeepHashes, false, false, SkipFileType.None, false, false, _tmpdir, false, null, true, null); depot.BucketBy(SortedBy.SHA1, DedupeType.None); // Set the base queries to use string crcquery = "INSERT OR IGNORE INTO crc (crc) VALUES"; string md5query = "INSERT OR IGNORE INTO md5 (md5) VALUES"; string sha1query = "INSERT OR IGNORE INTO sha1 (sha1, depot) VALUES"; string crcsha1query = "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES"; string md5sha1query = "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES"; // Once we have both, check for any new files List <string> dupehashes = new List <string>(); List <string> keys = depot.Keys; foreach (string key in keys) { List <DatItem> roms = depot[key]; foreach (Rom rom in roms) { if (hashes.Contains(rom.SHA1)) { dupehashes.Add(rom.SHA1); hashes.Remove(rom.SHA1); } else if (!dupehashes.Contains(rom.SHA1)) { if (!String.IsNullOrWhiteSpace(rom.CRC)) { crcquery += " (\"" + rom.CRC + "\"),"; } if (!String.IsNullOrWhiteSpace(rom.MD5)) { md5query += " (\"" + rom.MD5 + "\"),"; } if (!String.IsNullOrWhiteSpace(rom.SHA1)) { sha1query += " (\"" + rom.SHA1 + "\", \"" + depotname + "\"),"; if (!String.IsNullOrWhiteSpace(rom.CRC)) { crcsha1query += " (\"" + rom.CRC + "\", \"" + rom.SHA1 + "\"),"; } if (!String.IsNullOrWhiteSpace(rom.MD5)) { md5sha1query += " (\"" + rom.MD5 + "\", \"" + rom.SHA1 + "\"),"; } } } } } // Now run the queries after fixing them if (crcquery != "INSERT OR IGNORE INTO crc (crc) VALUES") { slc = new SqliteCommand(crcquery.TrimEnd(','), dbc); slc.ExecuteNonQuery(); } if (md5query != "INSERT OR IGNORE INTO md5 (md5) VALUES") { slc = new SqliteCommand(md5query.TrimEnd(','), dbc); slc.ExecuteNonQuery(); } if (sha1query != "INSERT OR IGNORE INTO sha1 (sha1, depot) VALUES") { slc = new SqliteCommand(sha1query.TrimEnd(','), dbc); slc.ExecuteNonQuery(); } if (crcsha1query != "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES") { slc = new SqliteCommand(crcsha1query.TrimEnd(','), dbc); slc.ExecuteNonQuery(); } if (md5sha1query != "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES") { slc = new SqliteCommand(md5sha1query.TrimEnd(','), dbc); slc.ExecuteNonQuery(); } // Now that we've added the information, we get to remove all of the hashes that we want to query = @"DELETE FROM sha1 JOIN crcsha1 ON sha1.sha1=crcsha1.sha1 JOIN md5sha1 ON sha1.sha1=md5sha1.sha1 JOIN crc ON crcsha1.crc=crc.crc JOIN md5 ON md5sha1.md5=md5.md5 WHERE sha1.sha1 IN (""" + String.Join("\",\"", hashes) + "\")"; slc = new SqliteCommand(query, dbc); slc.ExecuteNonQuery(); // Dispose of the database connection slc.Dispose(); dbc.Dispose(); } }
/// <summary> /// Wrap refreshing the database with potentially new dats /// </summary> /// <param name="workers">How many workers to launch for the job, default from config</param> /// <param name="missingSha1s">Write paths of dats with missing sha1s into this file</param> private static void InitRefreshDats( int workers, string missingSha1s) { // Make sure the db is set if (String.IsNullOrWhiteSpace(_db)) { _db = "db.sqlite"; _connectionString = "Data Source=" + _db + ";Version = 3;"; } // Make sure the file exists if (!File.Exists(_db)) { DatabaseTools.EnsureDatabase(_dbSchema, _db, _connectionString); } // Make sure the dats dir is set if (String.IsNullOrWhiteSpace(_dats)) { _dats = "dats"; } _dats = Path.Combine(Globals.ExeDir, _dats); // Make sure the folder exists if (!Directory.Exists(_dats)) { Directory.CreateDirectory(_dats); } // First get a list of SHA-1's from the input DATs DatFile datroot = new DatFile { Type = "SuperDAT", }; // TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually datroot.PopulateFromDir(_dats, Hash.DeepHashes, false, false, SkipFileType.None, false, false, _tmpdir, false, null, true, null); datroot.BucketBy(SortedBy.SHA1, DedupeType.None); // Create a List of dat hashes in the database (SHA-1) List <string> databaseDats = new List <string>(); List <string> unneeded = new List <string>(); SqliteConnection dbc = new SqliteConnection(_connectionString); dbc.Open(); // Populate the List from the database InternalStopwatch watch = new InternalStopwatch("Populating the list of existing DATs"); string query = "SELECT DISTINCT hash FROM dat"; SqliteCommand slc = new SqliteCommand(query, dbc); SqliteDataReader sldr = slc.ExecuteReader(); if (sldr.HasRows) { sldr.Read(); string hash = sldr.GetString(0); if (datroot.Contains(hash)) { datroot.Remove(hash); databaseDats.Add(hash); } else if (!databaseDats.Contains(hash)) { unneeded.Add(hash); } } datroot.BucketBy(SortedBy.Game, DedupeType.None, norename: true); watch.Stop(); slc.Dispose(); sldr.Dispose(); // Loop through the Dictionary and add all data watch.Start("Adding new DAT information"); foreach (string key in datroot.Keys) { foreach (Rom value in datroot[key]) { AddDatToDatabase(value, dbc); } } watch.Stop(); // Now loop through and remove all references to old Dats if (unneeded.Count > 0) { watch.Start("Removing unmatched DAT information"); query = "DELETE FROM dat WHERE"; foreach (string dathash in unneeded) { query += " OR hash=\"" + dathash + "\""; } query = query.Replace("WHERE OR", "WHERE"); slc = new SqliteCommand(query, dbc); slc.ExecuteNonQuery(); slc.Dispose(); watch.Stop(); } dbc.Dispose(); }