File indexing completed on 2024-05-19 05:42:11
0001 // ct_lvtmdb_objectstore.h -*-C++-*- 0002 0003 /* 0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk> 0005 // SPDX-License-Identifier: Apache-2.0 0006 // 0007 // Licensed under the Apache License, Version 2.0 (the "License"); 0008 // you may not use this file except in compliance with the License. 0009 // You may obtain a copy of the License at 0010 // 0011 // http://www.apache.org/licenses/LICENSE-2.0 0012 // 0013 // Unless required by applicable law or agreed to in writing, software 0014 // distributed under the License is distributed on an "AS IS" BASIS, 0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0016 // See the License for the specific language governing permissions and 0017 // limitations under the License. 0018 */ 0019 0020 #ifndef INCLUDED_CT_LVTMDB_OBJECTSTORE 0021 #define INCLUDED_CT_LVTMDB_OBJECTSTORE 0022 0023 //@PURPOSE: Store lvtmdb::DbObjects with fast lookup 0024 // 0025 //@CLASSES: 0026 // lvtldr::ObjectStore: Append-only store of DbObjects with fast lookup 0027 0028 #include <lvtmdb_export.h> 0029 0030 #include <ct_lvtmdb_lockable.h> 0031 #include <ct_lvtmdb_util.h> 0032 0033 #include <ct_lvtshr_graphenums.h> 0034 0035 #include <QList> 0036 0037 #include <result/result.hpp> 0038 0039 #include <filesystem> 0040 #include <memory> 0041 #include <set> 0042 #include <unordered_map> 0043 0044 namespace Codethink::lvtmdb { 0045 0046 // FORWARD DECLARATIONS 0047 class ComponentObject; 0048 class ErrorObject; 0049 class FieldObject; 0050 class FileObject; 0051 class FunctionObject; 0052 class MethodObject; 0053 class NamespaceObject; 0054 class PackageObject; 0055 class RepositoryObject; 0056 class TypeObject; 0057 class VariableObject; 0058 0059 // ========================== 0060 // class ObjectStore 0061 // ========================== 0062 0063 class LVTMDB_EXPORT ObjectStore : public Lockable { 0064 // Append-only store of DbObjects with fast lookup 0065 // The caller must acquire a ROLock or RWLock before calling a const method 0066 // The caller must acquire a RWLock before calling a non-const method 0067 // These locks do not need to be held for the duration of object access 0068 0069 private: 0070 // TYPES 0071 struct Private; 0072 0073 // DATA 0074 std::unique_ptr<Private> d; 0075 0076 public: 0077 // CREATORS 0078 ObjectStore(); 0079 0080 ~ObjectStore() noexcept override; 0081 0082 ObjectStore(const ObjectStore& other) = delete; 0083 0084 enum class State : int { 0085 // It is important this is an int so it can be stored in DbOption 0086 Error, 0087 ManuallyStopped, 0088 NoneReady, 0089 PhysicalReady, // Physical parse finished correctly 0090 PhysicalError, // Parse error, but it should still be able to visualize physical information. 0091 AllReady, // Physical and logical finished correctly. 0092 LogicalError // Physical finished correctly, and Logical finished with error. 0093 }; 0094 0095 void setState(State state); 0096 // indicates if this ObjectStorage contains partial data, error, is empty, or finished correctly. 0097 0098 State state() const; 0099 0100 // ACCESSORS 0101 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<ComponentObject>>& components() const; 0102 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<ErrorObject>>& errors() const; 0103 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<FieldObject>>& fields() const; 0104 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<FileObject>>& files() const; 0105 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<FunctionObject>>& functions() const; 0106 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<MethodObject>>& methods() const; 0107 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<NamespaceObject>>& namespaces() const; 0108 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<RepositoryObject>>& repositories() const; 0109 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<PackageObject>>& packages() const; 0110 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<TypeObject>>& types() const; 0111 [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<VariableObject>>& variables() const; 0112 0113 // interface to look up by qualified name: 0114 // Return a matching object or nullptr if nothing was found 0115 [[nodiscard]] FileObject *getFile(const std::string& qualifiedName) const; 0116 [[nodiscard]] ComponentObject *getComponent(const std::string& qualifiedName) const; 0117 [[nodiscard]] RepositoryObject *getRepository(const std::string& qualifiedName) const; 0118 [[nodiscard]] PackageObject *getPackage(const std::string& qualifiedName) const; 0119 [[nodiscard]] ErrorObject * 0120 getError(const std::string& qualifiedName, const std::string& errorMessage, const std::string& fileName) const; 0121 [[nodiscard]] NamespaceObject *getNamespace(const std::string& qualifiedName) const; 0122 [[nodiscard]] VariableObject *getVariable(const std::string& qualifiedName) const; 0123 [[nodiscard]] FunctionObject *getFunction(const std::string& qualifiedName, 0124 const std::string& signature, 0125 const std::string& templateParameters, 0126 const std::string& returnType) const; 0127 [[nodiscard]] TypeObject *getType(const std::string& qualifiedName) const; 0128 [[nodiscard]] FieldObject *getField(const std::string& qualifiedName) const; 0129 [[nodiscard]] MethodObject *getMethod(const std::string& qualifiedName, 0130 const std::string& signature, 0131 const std::string& templateParameters, 0132 const std::string& returnType) const; 0133 0134 [[nodiscard]] std::vector<PackageObject *> getAllPackages() const; 0135 [[nodiscard]] std::vector<FileObject *> getAllFiles() const; 0136 0137 // *do not* call those methods - this is extremely easy to break. 0138 // there's a correct order to be called, and currently, it all starts 0139 // with `removeFile` - removeFile will then descend and delete everything 0140 // from inside of all the other files. 0141 // return the list of deleted files, since this can propagate to more files. 0142 QList<std::string> removeFile(FileObject *file, std::set<intptr_t>& removed); 0143 void removeNamespace(NamespaceObject *nmspc); 0144 void removeType(TypeObject *type); 0145 void removeMethod(MethodObject *method); 0146 void removeField(FieldObject *field); 0147 void removeFunction(FunctionObject *func); 0148 void removeVariable(VariableObject *var); 0149 void removeComponent(ComponentObject *comp); 0150 void removePackage(PackageObject *pkg, std::set<intptr_t>& removed); 0151 0152 // MODIFIERS 0153 // This should be used by a DataWriter - such as SociWriter, 0154 // to save the contents of this ObjectStore to disk. 0155 template<typename DatabaseAccessWriter> 0156 void writeToDatabase(DatabaseAccessWriter& writer) 0157 { 0158 writer.writeFrom(*this); 0159 } 0160 0161 struct ReadFromDatabaseError { 0162 std::string what; 0163 }; 0164 0165 template<typename DatabaseAccessReader> 0166 cpp::result<void, ReadFromDatabaseError> readFromDatabase(DatabaseAccessReader& reader, std::string db) 0167 // DatabaseAccessReader is a class that implements readInto(ObjectStore& obj, std::string db); 0168 // db is a path in disk *or* ":memory:", so we can't use std::filesystem::path' 0169 { 0170 return reader.readInto(*this, db); 0171 } 0172 // This will call clear(). Be extremely careful there aren't any 0173 // DbObject pointers left dangling! 0174 0175 // interface to lookup or construct new DbObjects 0176 // Returns a pointer to the new object 0177 FileObject *getOrAddFile(const std::string& qualifiedName, 0178 std::string name, 0179 bool isHeader, 0180 std::string hash, 0181 PackageObject *package, 0182 ComponentObject *component); 0183 0184 ComponentObject *getOrAddComponent(const std::string& qualifiedName, std::string name, PackageObject *package); 0185 RepositoryObject *getOrAddRepository(const std::string& name, const std::string& diskPath); 0186 0187 PackageObject *getOrAddPackage(const std::string& qualifiedName, 0188 std::string name, 0189 std::string diskPath, 0190 PackageObject *parent, 0191 RepositoryObject *repository); 0192 0193 ErrorObject *getOrAddError(lvtmdb::MdbUtil::ErrorKind errorKind, 0194 std::string qualifiedName, 0195 std::string errorMessage, 0196 std::string fileName); 0197 0198 NamespaceObject *getOrAddNamespace(const std::string& qualifiedName, std::string name, NamespaceObject *parent); 0199 0200 VariableObject *getOrAddVariable(const std::string& qualifiedName, 0201 std::string name, 0202 std::string signature, 0203 bool isGlobal, 0204 NamespaceObject *parent); 0205 0206 FunctionObject *getOrAddFunction(std::string qualifiedName, 0207 std::string name, 0208 std::string signature, 0209 std::string returnType, 0210 std::string templateParameters, 0211 NamespaceObject *parent); 0212 0213 TypeObject *getOrAddType(const std::string& qualifiedName, 0214 std::string name, 0215 lvtshr::UDTKind kind, 0216 lvtshr::AccessSpecifier access, 0217 NamespaceObject *nmspc, 0218 PackageObject *pkg, 0219 TypeObject *parent); 0220 0221 FieldObject *getOrAddField(const std::string& qualifiedName, 0222 std::string name, 0223 std::string signature, 0224 lvtshr::AccessSpecifier access, 0225 bool isStatic, 0226 TypeObject *parent); 0227 0228 MethodObject *getOrAddMethod(std::string qualifiedName, 0229 std::string name, 0230 std::string signature, 0231 std::string returnType, 0232 std::string templateParameters, 0233 lvtshr::AccessSpecifier access, 0234 bool isVirtual, 0235 bool isPure, 0236 bool isStatic, 0237 bool isConst, 0238 TypeObject *parent); 0239 0240 void clear(); 0241 }; 0242 0243 } // namespace Codethink::lvtmdb 0244 0245 #endif // INCLUDED_CT_LVTMDB_OBJECTSTORE