Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        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);
        }