1 // kv_catalog.h
2 
3 
4 /**
5  *    Copyright (C) 2018-present MongoDB, Inc.
6  *
7  *    This program is free software: you can redistribute it and/or modify
8  *    it under the terms of the Server Side Public License, version 1,
9  *    as published by MongoDB, Inc.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    Server Side Public License for more details.
15  *
16  *    You should have received a copy of the Server Side Public License
17  *    along with this program. If not, see
18  *    <http://www.mongodb.com/licensing/server-side-public-license>.
19  *
20  *    As a special exception, the copyright holders give permission to link the
21  *    code of portions of this program with the OpenSSL library under certain
22  *    conditions as described in each individual source file and distribute
23  *    linked combinations including the program with the OpenSSL library. You
24  *    must comply with the Server Side Public License in all respects for
25  *    all of the code used other than as permitted herein. If you modify file(s)
26  *    with this exception, you may extend this exception to your version of the
27  *    file(s), but you are not obligated to do so. If you do not wish to do so,
28  *    delete this exception statement from your version. If you delete this
29  *    exception statement from all source files in the program, then also delete
30  *    it in the license file.
31  */
32 
33 #pragma once
34 
35 #include <map>
36 #include <memory>
37 #include <string>
38 
39 #include "mongo/base/string_data.h"
40 #include "mongo/db/catalog/collection_options.h"
41 #include "mongo/db/record_id.h"
42 #include "mongo/db/storage/bson_collection_catalog_entry.h"
43 #include "mongo/db/storage/kv/kv_prefix.h"
44 #include "mongo/stdx/mutex.h"
45 
46 namespace mongo {
47 
48 class OperationContext;
49 class RecordStore;
50 
51 class KVCatalog {
52 public:
53     class FeatureTracker;
54 
55     /**
56      * @param rs - does NOT take ownership. The RecordStore must be thread-safe, in particular
57      * with concurrent calls to RecordStore::find, updateRecord, insertRecord, deleteRecord and
58      * dataFor. The KVCatalog does not utilize Cursors and those methods may omit further
59      * protection.
60      */
61     KVCatalog(RecordStore* rs, bool directoryPerDb, bool directoryForIndexes);
62     ~KVCatalog();
63 
64     void init(OperationContext* opCtx);
65 
66     void getAllCollections(std::vector<std::string>* out) const;
67 
68     /**
69      * @return error or ident for instance
70      */
71     Status newCollection(OperationContext* opCtx,
72                          StringData ns,
73                          const CollectionOptions& options,
74                          KVPrefix prefix);
75 
76     std::string getCollectionIdent(StringData ns) const;
77 
78     std::string getIndexIdent(OperationContext* opCtx, StringData ns, StringData idName) const;
79 
80     const BSONCollectionCatalogEntry::MetaData getMetaData(OperationContext* opCtx, StringData ns);
81     void putMetaData(OperationContext* opCtx,
82                      StringData ns,
83                      BSONCollectionCatalogEntry::MetaData& md);
84 
85     Status renameCollection(OperationContext* opCtx,
86                             StringData fromNS,
87                             StringData toNS,
88                             bool stayTemp);
89 
90     Status dropCollection(OperationContext* opCtx, StringData ns);
91 
92     std::vector<std::string> getAllIdentsForDB(StringData db) const;
93     std::vector<std::string> getAllIdents(OperationContext* opCtx) const;
94 
95     bool isUserDataIdent(StringData ident) const;
96 
getFeatureTracker()97     FeatureTracker* getFeatureTracker() const {
98         invariant(_featureTracker);
99         return _featureTracker.get();
100     }
101 
102     std::string getFilesystemPathForDb(const std::string& dbName) const;
103 
104 private:
105     class AddIdentChange;
106     class RemoveIdentChange;
107 
108     BSONObj _findEntry(OperationContext* opCtx, StringData ns, RecordId* out = NULL) const;
109 
110     /**
111      * Generates a new unique identifier for a new "thing".
112      * @param ns - the containing ns
113      * @param kind - what this "thing" is, likely collection or index
114      */
115     std::string _newUniqueIdent(StringData ns, const char* kind);
116 
117     // Helpers only used by constructor and init(). Don't call from elsewhere.
118     static std::string _newRand();
119     bool _hasEntryCollidingWithRand() const;
120 
121     RecordStore* _rs;  // not owned
122     const bool _directoryPerDb;
123     const bool _directoryForIndexes;
124 
125     // These two are only used for ident generation inside _newUniqueIdent.
126     std::string _rand;  // effectively const after init() returns
127     AtomicUInt64 _next;
128 
129     struct Entry {
EntryEntry130         Entry() {}
EntryEntry131         Entry(std::string i, RecordId l) : ident(i), storedLoc(l) {}
132         std::string ident;
133         RecordId storedLoc;
134     };
135     typedef std::map<std::string, Entry> NSToIdentMap;
136     NSToIdentMap _idents;
137     mutable stdx::mutex _identsLock;
138 
139     // Manages the feature document that may be present in the KVCatalog. '_featureTracker' is
140     // guaranteed to be non-null after KVCatalog::init() is called.
141     std::unique_ptr<FeatureTracker> _featureTracker;
142 };
143 }
144