void UpdateEntry(AppliedFileEntry entry, uint speed) { string update = $"REPLACE INTO `updates` (`name`, `hash`, `state`, `speed`) VALUES (\"{entry.Name}\", \"{entry.Hash}\", \'{entry.State}\', {speed})"; // Update database _database.Execute(update); }
void UpdateEntry(AppliedFileEntry entry, uint speed) { string update = "REPLACE INTO `updates` (`name`, `hash`, `state`, `speed`) VALUES (\"" + entry.Name + "\", \"" + entry.Hash + "\", \'" + entry.State + "\', " + speed + ")"; // Update database _database.Execute(update); }
Dictionary <string, AppliedFileEntry> ReceiveAppliedFiles() { Dictionary <string, AppliedFileEntry> map = new Dictionary <string, AppliedFileEntry>(); SQLResult result = _database.Query("SELECT `name`, `hash`, `state`, UNIX_TIMESTAMP(`timestamp`) FROM `updates` ORDER BY `name` ASC"); if (result.IsEmpty()) { return(map); } do { AppliedFileEntry entry = new AppliedFileEntry(result.Read <string>(0), result.Read <string>(1), result.Read <string>(2).ToEnum <State>(), result.Read <ulong>(3)); map.Add(entry.Name, entry); }while (result.NextRow()); return(map); }
public bool Update() { Log.outInfo(LogFilter.SqlUpdates, $"Updating {_database.GetDatabaseName()} database..."); string sourceDirectory = GetSourceDirectory(); if (!Directory.Exists(sourceDirectory)) { Log.outError(LogFilter.SqlUpdates, $"DBUpdater: Given source directory {sourceDirectory} does not exist, skipped!"); return(false); } var availableFiles = GetFileList(); var appliedFiles = ReceiveAppliedFiles(); bool redundancyChecks = ConfigMgr.GetDefaultValue("Updates.Redundancy", true); bool archivedRedundancy = ConfigMgr.GetDefaultValue("Updates.Redundancy", true); UpdateResult result = new UpdateResult(); // Count updates foreach (var entry in appliedFiles) { if (entry.Value.State == State.RELEASED) { ++result.recent; } else { ++result.archived; } } foreach (var availableQuery in availableFiles) { Log.outDebug(LogFilter.SqlUpdates, $"Checking update \"{availableQuery.GetFileName()}\"..."); var applied = appliedFiles.LookupByKey(availableQuery.GetFileName()); if (applied != null) { // If redundancy is disabled skip it since the update is already applied. if (!redundancyChecks) { Log.outDebug(LogFilter.SqlUpdates, "Update is already applied, skipping redundancy checks."); appliedFiles.Remove(availableQuery.GetFileName()); continue; } // If the update is in an archived directory and is marked as archived in our database skip redundancy checks (archived updates never change). if (!archivedRedundancy && (applied.State == State.ARCHIVED) && (availableQuery.state == State.ARCHIVED)) { Log.outDebug(LogFilter.SqlUpdates, "Update is archived and marked as archived in database, skipping redundancy checks."); appliedFiles.Remove(availableQuery.GetFileName()); continue; } } // Calculate hash string hash = CalculateHash(availableQuery.path); UpdateMode mode = UpdateMode.Apply; // Update is not in our applied list if (applied == null) { // Catch renames (different filename but same hash) var hashIter = appliedFiles.Values.FirstOrDefault(p => p.Hash == hash); if (hashIter != null) { // Check if the original file was removed if not we've got a problem. var renameFile = availableFiles.Find(p => p.GetFileName() == hashIter.Name); if (renameFile != null) { Log.outWarn(LogFilter.SqlUpdates, $"Seems like update \"{availableQuery.GetFileName()}\" \'{hash.Substring(0, 7)}\' was renamed, but the old file is still there! " + $"Trade it as a new file! (Probably its an unmodified copy of file \"{renameFile.GetFileName()}\")"); } // Its save to trade the file as renamed here else { Log.outInfo(LogFilter.SqlUpdates, $"Renaming update \"{hashIter.Name}\" to \"{availableQuery.GetFileName()}\" \'{hash.Substring(0, 7)}\'."); RenameEntry(hashIter.Name, availableQuery.GetFileName()); appliedFiles.Remove(hashIter.Name); continue; } } // Apply the update if it was never seen before. else { Log.outInfo(LogFilter.SqlUpdates, $"Applying update \"{availableQuery.GetFileName()}\" \'{hash.Substring(0, 7)}\'..."); } } // Rehash the update entry if it is contained in our database but with an empty hash. else if (ConfigMgr.GetDefaultValue("Updates.AllowRehash", true) && string.IsNullOrEmpty(applied.Hash)) { mode = UpdateMode.Rehash; Log.outInfo(LogFilter.SqlUpdates, $"Re-hashing update \"{availableQuery.GetFileName()}\" \'{hash.Substring(0, 7)}\'..."); } else { // If the hash of the files differs from the one stored in our database reapply the update (because it was changed). if (applied.Hash != hash && applied.State != State.ARCHIVED) { Log.outInfo(LogFilter.SqlUpdates, $"Reapplying update \"{availableQuery.GetFileName()}\" \'{applied.Hash.Substring(0, 7)}\' . \'{hash.Substring(0, 7)}\' (it changed)..."); } else { // If the file wasn't changed and just moved update its state if necessary. if (applied.State != availableQuery.state) { Log.outDebug(LogFilter.SqlUpdates, $"Updating state of \"{availableQuery.GetFileName()}\" to \'{availableQuery.state}\'..."); UpdateState(availableQuery.GetFileName(), availableQuery.state); } Log.outDebug(LogFilter.SqlUpdates, $"Update is already applied and is matching hash \'{hash.Substring(0, 7)}\'."); appliedFiles.Remove(applied.Name); continue; } } uint speed = 0; AppliedFileEntry file = new AppliedFileEntry(availableQuery.GetFileName(), hash, availableQuery.state, 0); switch (mode) { case UpdateMode.Apply: speed = ApplyTimedFile(availableQuery.path); goto case UpdateMode.Rehash; case UpdateMode.Rehash: UpdateEntry(file, speed); break; } if (applied != null) { appliedFiles.Remove(applied.Name); } if (mode == UpdateMode.Apply) { ++result.updated; } } // Cleanup up orphaned entries if enabled if (!appliedFiles.Empty()) { int cleanDeadReferencesMaxCount = ConfigMgr.GetDefaultValue("Updates.CleanDeadRefMaxCount", 3); bool doCleanup = (cleanDeadReferencesMaxCount < 0) || (appliedFiles.Count <= cleanDeadReferencesMaxCount); foreach (var entry in appliedFiles) { Log.outWarn(LogFilter.SqlUpdates, $"File \'{entry.Key}\' was applied to the database but is missing in your update directory now!"); if (doCleanup) { Log.outInfo(LogFilter.SqlUpdates, $"Deleting orphaned entry \'{entry.Key}\'..."); } } if (doCleanup) { CleanUp(appliedFiles); } else { Log.outError(LogFilter.SqlUpdates, $"Cleanup is disabled! There are {appliedFiles.Count} dirty files that were applied to your database but are now missing in your source directory!"); } } string info = $"Containing {result.recent} new and {result.archived} archived updates."; if (result.updated == 0) { Log.outInfo(LogFilter.SqlUpdates, $"{_database.GetDatabaseName()} database is up-to-date! {info}"); } else { Log.outInfo(LogFilter.SqlUpdates, $"Applied {result.updated} query(s). {info}"); } return(true); }