ConfigurationDatabase.h (6654B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include "ConfigurationSetChangeData.h" 5 #include <winget/SQLiteWrapper.h> 6 #include <winget/SQLiteDynamicStorage.h> 7 #include <winrt/Microsoft.Management.Configuration.h> 8 #include <memory> 9 #include <optional> 10 #include <vector> 11 12 namespace winrt::Microsoft::Management::Configuration::implementation 13 { 14 // Forward declarations 15 struct ConfigurationSet; 16 struct IConfigurationDatabase; 17 18 // Allows access to the configuration database. 19 struct ConfigurationDatabase 20 { 21 using ConfigurationSetPtr = winrt::com_ptr<implementation::ConfigurationSet>; 22 23 ConfigurationDatabase(); 24 25 ConfigurationDatabase(const ConfigurationDatabase&) = delete; 26 ConfigurationDatabase& operator=(const ConfigurationDatabase&) = delete; 27 28 ConfigurationDatabase(ConfigurationDatabase&&); 29 ConfigurationDatabase& operator=(ConfigurationDatabase&&); 30 31 ~ConfigurationDatabase(); 32 33 // Ensures that the database connection is established and the schema interface is created appropriately. 34 // If `createIfNeeded` is false, this function will not create the database if it does not exist. 35 // If not connected, any read methods will return empty results and any write methods will throw. 36 void EnsureOpened(bool createIfNeeded = true); 37 38 // Gets all of the configuration sets from the database. 39 std::vector<ConfigurationSetPtr> GetSetHistory() const; 40 41 // Gets the set with the given identifier. 42 ConfigurationSetPtr GetSet(const GUID& instanceIdentifier) const; 43 44 // Writes the given set to the database history, attempting to merge with a matching set if one exists unless preferNewHistory is true. 45 void WriteSetHistory(const Configuration::ConfigurationSet& configurationSet, bool preferNewHistory); 46 47 // Removes the given set from the database history if it is present. 48 void RemoveSetHistory(const Configuration::ConfigurationSet& configurationSet); 49 50 // Adds a new queue item for the given configuration set and object name. 51 void AddQueueItem(const Configuration::ConfigurationSet& configurationSet, const std::string& objectName); 52 53 // Sets the queue item with the given object name as active. 54 void SetActiveQueueItem(const std::string& objectName); 55 56 // Data about a queue item. 57 struct QueueItem 58 { 59 GUID SetInstanceIdentifier{}; 60 std::string ObjectName; 61 std::chrono::system_clock::time_point QueuedAt; 62 DWORD ProcessId{}; 63 bool Active = false; 64 }; 65 66 // Gets all queue items in queue order (item at index 0 is active/next). 67 std::vector<QueueItem> GetQueueItems() const; 68 69 // Removes the queue item with the given object name. 70 void RemoveQueueItem(const std::string& objectName); 71 72 // A status line item. 73 struct StatusItem 74 { 75 int64_t ChangeIdentifier; 76 std::chrono::system_clock::time_point ChangeTime; 77 GUID SetInstanceIdentifier; 78 bool InQueue; 79 std::optional<GUID> UnitInstanceIdentifier; 80 int32_t State; 81 std::optional<HRESULT> ResultCode; 82 std::string ResultDescription; 83 std::string ResultDetails; 84 ConfigurationUnitResultSource ResultSource; 85 }; 86 87 // Gets all changed status items after the given change identifier. 88 std::vector<StatusItem> GetStatusSince(int64_t changeIdentifier) const; 89 90 // The status baseline data. 91 struct StatusBaseline 92 { 93 int64_t ChangeIdentifier = 0; 94 std::vector<StatusItem> SetStatus; 95 }; 96 97 // Gets the current status baseline. 98 StatusBaseline GetStatusBaseline() const; 99 100 // Data about a status change listener. 101 struct StatusChangeListener 102 { 103 std::string ObjectName; 104 std::chrono::system_clock::time_point Started; 105 DWORD ProcessId{}; 106 }; 107 108 // Adds a listener to the database. 109 void AddListener(const std::string& objectName); 110 111 // Removes a listener from the database. 112 void RemoveListener(const std::string& objectName); 113 114 // Gets all listeners in the database. 115 std::vector<StatusChangeListener> GetChangeListeners() const; 116 117 // Updates the set state in the database. 118 void UpdateSetState(const guid& setInstanceIdentifier, ConfigurationSetState state); 119 120 // Updates the set "in queue" state in the database. 121 void UpdateSetInQueue(const guid& setInstanceIdentifier, bool inQueue); 122 123 // Updates the unit state in the database. 124 void UpdateUnitState(const guid& setInstanceIdentifier, const com_ptr<implementation::ConfigurationSetChangeData>& changeData); 125 126 // Read various status values. 127 ConfigurationSetState GetSetState(const guid& instanceIdentifier); 128 std::chrono::system_clock::time_point GetSetFirstApply(const guid& instanceIdentifier); 129 std::chrono::system_clock::time_point GetSetApplyBegun(const guid& instanceIdentifier); 130 std::chrono::system_clock::time_point GetSetApplyEnded(const guid& instanceIdentifier); 131 ConfigurationUnitState GetUnitState(const guid& instanceIdentifier); 132 IConfigurationUnitResultInformation GetUnitResultInformation(const guid& instanceIdentifier); 133 134 private: 135 std::shared_ptr<AppInstaller::SQLite::SQLiteDynamicStorage> m_connection; 136 mutable std::shared_ptr<IConfigurationDatabase> m_database; 137 138 using TransactionLock = decltype(m_connection->TryBeginTransaction({}, true)); 139 140 // Begins a transaction, which may require upgrading to a newer schema version. 141 TransactionLock BeginTransaction(std::string_view name, bool forWrite, std::shared_ptr<IConfigurationDatabase>& database) const; 142 143 // Performs the boilerplate setup for a read, then executes the given operation. 144 template <typename OperationT> 145 auto ExecuteReadOperation(std::string_view operationName, OperationT&& operation, bool requireDatabase = false) const; 146 147 // Performs the boilerplate setup for a write, then executes the given operation. 148 template <typename OperationT> 149 void ExecuteWriteOperation(std::string_view operationName, OperationT&& operation, bool silentlyIgnoreNoDatabase = false); 150 }; 151 }