CheckpointDatabase.cpp (6857B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "Public/winget/CheckpointDatabase.h" 5 #include "Microsoft/Schema/ICheckpointDatabase.h" 6 #include "Microsoft/Schema/Checkpoint_1_0/CheckpointDatabaseInterface.h" 7 8 namespace AppInstaller::Repository::Microsoft 9 { 10 namespace 11 { 12 // Creates the ICheckpointDatabase interface object for the given version. 13 std::unique_ptr<Schema::ICheckpointDatabase> CreateICheckpointDatabase(const SQLite::Version& version) 14 { 15 if (version == SQLite::Version{ 1, 0 } || 16 version.MajorVersion == 1 || 17 version.IsLatest()) 18 { 19 return std::make_unique<Schema::Checkpoint_V1_0::CheckpointDatabaseInterface>(); 20 } 21 22 THROW_HR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)); 23 } 24 } 25 26 CheckpointDatabase::CheckpointDatabase(CheckpointDatabase&&) = default; 27 CheckpointDatabase& CheckpointDatabase::operator=(CheckpointDatabase&&) = default; 28 29 std::shared_ptr<CheckpointDatabase> CheckpointDatabase::CreateNew(const std::string& filePath, SQLite::Version version) 30 { 31 AICLI_LOG(Repo, Info, << "Creating new Checkpoint database with version [" << version << "] at '" << filePath << "'"); 32 CheckpointDatabase result{ filePath, version }; 33 34 SQLite::Savepoint savepoint = SQLite::Savepoint::Create(result.m_dbconn, "CheckpointDatabase_CreateNew"); 35 36 // Use calculated version, as incoming version could be 'latest' 37 result.m_version.SetSchemaVersion(result.m_dbconn); 38 39 result.m_interface->CreateTables(result.m_dbconn); 40 41 result.SetLastWriteTime(); 42 43 savepoint.Commit(); 44 45 return std::make_shared<CheckpointDatabase>(std::move(result)); 46 } 47 48 std::shared_ptr<CheckpointDatabase> CheckpointDatabase::Open(const std::string& filePath, SQLite::SQLiteStorageBase::OpenDisposition disposition, Utility::ManagedFile&& indexFile) 49 { 50 return std::make_shared<CheckpointDatabase>(CheckpointDatabase{ filePath, disposition, std::move(indexFile) }); 51 } 52 53 bool CheckpointDatabase::IsEmpty() 54 { 55 return m_interface->IsEmpty(m_dbconn); 56 } 57 58 CheckpointDatabase::IdType CheckpointDatabase::AddCheckpoint(std::string_view checkpointName) 59 { 60 std::lock_guard<std::mutex> lockInterface{ *m_interfaceLock }; 61 AICLI_LOG(Repo, Verbose, << "Adding checkpoint [" << checkpointName << "]"); 62 63 SQLite::Savepoint savepoint = SQLite::Savepoint::Create(m_dbconn, "CheckpointDatabase_addCheckpoint"); 64 65 IdType result = m_interface->AddCheckpoint(m_dbconn, checkpointName); 66 67 SetLastWriteTime(); 68 savepoint.Commit(); 69 return result; 70 } 71 72 std::vector<CheckpointDatabase::IdType> CheckpointDatabase::GetCheckpointIds() 73 { 74 return m_interface->GetCheckpointIds(m_dbconn); 75 } 76 77 bool CheckpointDatabase::HasDataField(IdType checkpointId, int type, const std::string& name) 78 { 79 return m_interface->GetCheckpointDataFieldValues(m_dbconn, checkpointId, type, name).has_value(); 80 } 81 82 std::vector<int> CheckpointDatabase::GetDataTypes(IdType checkpointId) 83 { 84 return m_interface->GetCheckpointDataTypes(m_dbconn, checkpointId); 85 } 86 87 std::vector<std::string> CheckpointDatabase::GetDataFieldNames(IdType checkpointId, int dataType) 88 { 89 return m_interface->GetCheckpointDataFields(m_dbconn, checkpointId, dataType); 90 } 91 92 void CheckpointDatabase::SetDataValue(IdType checkpointId, int dataType, const std::string& field, const std::vector<std::string>& values) 93 { 94 std::lock_guard<std::mutex> lockInterface{ *m_interfaceLock }; 95 AICLI_LOG(Repo, Verbose, << "Setting checkpoint data [" << dataType << "]"); 96 97 SQLite::Savepoint savepoint = SQLite::Savepoint::Create(m_dbconn, "CheckpointDatabase_setDataValue"); 98 99 m_interface->SetCheckpointDataValues(m_dbconn, checkpointId, dataType, field, values); 100 101 SetLastWriteTime(); 102 savepoint.Commit(); 103 } 104 105 void CheckpointDatabase::UpdateDataValue(IdType checkpointId, int dataType, const std::string& field, const std::vector<std::string>& values) 106 { 107 std::lock_guard<std::mutex> lockInterface{ *m_interfaceLock }; 108 AICLI_LOG(Repo, Verbose, << "Updating checkpoint data [" << dataType << "]"); 109 110 SQLite::Savepoint savepoint = SQLite::Savepoint::Create(m_dbconn, "CheckpointDatabase_updateDataValue"); 111 112 m_interface->RemoveCheckpointDataType(m_dbconn, checkpointId, dataType); 113 m_interface->SetCheckpointDataValues(m_dbconn, checkpointId, dataType, field, values); 114 115 SetLastWriteTime(); 116 savepoint.Commit(); 117 } 118 119 void CheckpointDatabase::RemoveDataType(IdType checkpointId, int dataType) 120 { 121 std::lock_guard<std::mutex> lockInterface{ *m_interfaceLock }; 122 AICLI_LOG(Repo, Verbose, << "Removing checkpoint data [" << dataType << "]"); 123 124 SQLite::Savepoint savepoint = SQLite::Savepoint::Create(m_dbconn, "CheckpointDatabase_removeDataValue"); 125 126 m_interface->RemoveCheckpointDataType(m_dbconn, checkpointId, dataType); 127 128 SetLastWriteTime(); 129 savepoint.Commit(); 130 } 131 132 std::string CheckpointDatabase::GetDataFieldSingleValue(IdType checkpointId, int dataType, const std::string& field) 133 { 134 const auto& values = m_interface->GetCheckpointDataFieldValues(m_dbconn, checkpointId, dataType, field); 135 136 if (!values.has_value()) 137 { 138 THROW_HR(E_UNEXPECTED); 139 } 140 141 return values.value()[0]; 142 } 143 144 std::vector<std::string> CheckpointDatabase::GetDataFieldMultiValue(IdType checkpointId, int dataType, const std::string& field) 145 { 146 const auto& values = m_interface->GetCheckpointDataFieldValues(m_dbconn, checkpointId, dataType, field); 147 148 if (!values.has_value()) 149 { 150 THROW_HR(E_UNEXPECTED); 151 } 152 153 return values.value(); 154 } 155 156 157 CheckpointDatabase::CheckpointDatabase(const std::string& target, SQLiteStorageBase::OpenDisposition disposition, Utility::ManagedFile&& indexFile) : 158 SQLiteStorageBase(target, disposition, std::move(indexFile)) 159 { 160 AICLI_LOG(Repo, Info, << "Opened Checkpoint Index with version [" << m_version << "], last write [" << GetLastWriteTime() << "]"); 161 m_interface = CreateICheckpointDatabase(m_version); 162 THROW_HR_IF(APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX, disposition == SQLiteStorageBase::OpenDisposition::ReadWrite && m_version != m_interface->GetVersion()); 163 } 164 165 CheckpointDatabase::CheckpointDatabase(const std::string& target, SQLite::Version version) : SQLiteStorageBase(target, version) 166 { 167 m_interface = CreateICheckpointDatabase(m_version); 168 m_version = m_interface->GetVersion(); 169 } 170 }