Reland D23318594 and D23318592 add recordbasenativesp instr
[hiphop-php.git] / hphp / runtime / vm / repo.h
blobbcdce9de1ac76b793e83a3219e92c54442a88dfb
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VM_REPO_H_
18 #define incl_HPHP_VM_REPO_H_
20 #include <vector>
21 #include <utility>
22 #include <string>
23 #include <memory>
24 #include <cstdlib>
26 #include <sqlite3.h>
28 // For getpwuid_r(3).
29 #include <sys/types.h>
30 #include <pwd.h>
32 #include "hphp/runtime/base/repo-autoload-map.h"
33 #include "hphp/runtime/vm/class.h"
34 #include "hphp/runtime/vm/func.h"
35 #include "hphp/runtime/vm/litstr-repo-proxy.h"
36 #include "hphp/runtime/vm/preclass-emitter.h"
37 #include "hphp/runtime/vm/record-emitter.h"
38 #include "hphp/runtime/vm/repo-status.h"
39 #include "hphp/runtime/vm/unit-emitter.h"
41 #include <folly/portability/Unistd.h>
43 namespace HPHP {
44 ///////////////////////////////////////////////////////////////////////////////
46 struct RepoAutoloadMapBuilder;
48 namespace Native {
49 struct FuncTable;
52 struct Repo : RepoProxy {
53 struct GlobalData;
55 // Do not directly instantiate this class; a thread-local creates one per
56 // thread on demand when Repo::get() is called.
57 static Repo& get();
58 // Prefork is called before forking. It attempts to shut down other
59 // threads and returns true if forking should be prevented, false if
60 // it's ok to proceed.
61 static bool prefork();
62 static void postfork(pid_t pid);
65 * In some command line programs that use the repo, it is necessary
66 * to shut it down at some point in the process. (See hhbbc.) This
67 * function accomplishes this.
69 static void shutdown();
71 Repo();
72 ~Repo() noexcept;
73 Repo(const Repo&) = delete;
74 Repo& operator=(const Repo&) = delete;
76 const char* dbName(int repoId) const {
77 assertx(repoId < RepoIdCount);
78 return kDbs[repoId];
80 sqlite3* dbc() const { return m_dbc; }
81 int repoIdForNewUnit(UnitOrigin unitOrigin) const {
82 switch (unitOrigin) {
83 case UnitOrigin::File:
84 return m_localWritable ? RepoIdLocal : RepoIdCentral;
85 case UnitOrigin::Eval:
86 return m_evalRepoId;
87 default:
88 assertx(false);
89 return RepoIdInvalid;
92 std::string repoName(int repoId) const {
93 switch (repoId) {
94 case RepoIdLocal: return m_localRepo;
95 case RepoIdCentral: return m_centralRepo;
96 default: return "?";
100 UnitRepoProxy& urp() { return m_urp; }
101 PreClassRepoProxy& pcrp() { return m_pcrp; }
102 RecordRepoProxy& rrp() { return m_rrp; }
103 FuncRepoProxy& frp() { return m_frp; }
104 LitstrRepoProxy& lsrp() { return m_lsrp; }
106 static void setCliFile(const std::string& cliFile);
108 std::unique_ptr<Unit> loadUnit(const folly::StringPiece name,
109 const SHA1& sha1,
110 const Native::FuncTable&);
111 void forgetUnit(const std::string& path);
112 RepoStatus findFile(const char* path, const std::string& root, SHA1& sha1);
113 std::optional<String> findPath(int64_t unitSn, const std::string& root);
114 RepoStatus findUnit(const char* path, const std::string& root, int64_t& unitSn);
115 RepoStatus insertSha1(UnitOrigin unitOrigin, UnitEmitter* ue, RepoTxn& txn);
116 void commitSha1(UnitOrigin unitOrigin, UnitEmitter* ue);
119 * Return the largest size for a static string that can be inserted into the
120 * repo.
122 size_t stringLengthLimit() const;
125 * Return a vector of (filepath, SHA1) for every unit in central
126 * repo.
128 std::vector<std::pair<std::string,SHA1>> enumerateUnits(
129 int repoId, bool warn);
132 * Check if the repo has global data. If it does the repo was built using
133 * WholeProgram mode.
135 bool hasGlobalData();
138 * Load the repo-global metadata table, including the global litstr
139 * table. Normally called during process initialization.
141 void loadGlobalData(bool readGlobalTables = true);
144 * Access to global data.
146 * Pre: loadGlobalData() already called, and
147 * RuntimeOption::RepoAuthoritative.
149 static const GlobalData& global() {
150 assertx(RuntimeOption::RepoAuthoritative);
151 return s_globalData;
155 * Used during repo creation to associate the supplied GlobalData
156 * with the repo that was being built. Also saves the global litstr
157 * table.
159 * No other threads may be reading or writing the repo GlobalData
160 * when this is called.
162 void saveGlobalData(GlobalData&& newData,
163 const RepoAutoloadMapBuilder& autoloadMapBuilder);
165 private:
167 * RepoStmts for setting/getting file hashes.
169 struct InsertFileHashStmt : public RepoProxy::Stmt {
170 InsertFileHashStmt(Repo& repo, int repoId) : Stmt(repo, repoId) {}
171 void insert(RepoTxn& txn, const StringData* path, const SHA1& sha1);
172 // throws(RepoExc)
175 struct GetFileHashStmt : public RepoProxy::Stmt {
176 GetFileHashStmt(Repo& repo, int repoId) : Stmt(repo, repoId) {}
177 RepoStatus get(const char* path, SHA1& sha1);
180 struct RemoveFileHashStmt : public RepoProxy::Stmt {
181 RemoveFileHashStmt(Repo& repo, int repoId) : Stmt(repo, repoId) {}
182 void remove(RepoTxn& txn, const std::string& path);
185 struct GetUnitPathStmt : public RepoProxy::Stmt {
186 GetUnitPathStmt(Repo& repo, int repoId) : Stmt(repo, repoId) {}
187 std::optional<String> get(int64_t unitSn);
190 struct GetUnitStmt : public RepoProxy::Stmt {
191 GetUnitStmt(Repo& repo, int repoId) : Stmt(repo, repoId) {}
192 RepoStatus get(const char* path, int64_t& unitSn);
195 InsertFileHashStmt m_insertFileHash[RepoIdCount];
196 GetFileHashStmt m_getFileHash[RepoIdCount];
197 RemoveFileHashStmt m_removeFileHash[RepoIdCount];
198 GetUnitPathStmt m_getUnitPath[RepoIdCount];
199 GetUnitStmt m_getUnit[RepoIdCount];
201 public:
202 std::string table(int repoId, const char* tablePrefix);
203 void exec(const std::string& sQuery); // throws(RepoExc)
205 RepoTxn begin(); // throws(RepoExc)
206 private:
207 friend struct RepoTxn;
208 void txPop(); // throws(RepoExc)
209 void rollback(); // nothrow
210 void commit(); // throws(RepoExc)
211 public:
212 RepoStatus insertUnit(UnitEmitter* ue, UnitOrigin unitOrigin,
213 RepoTxn& txn, bool usePreAllocatedUnitSn); // nothrow
214 void commitUnit(UnitEmitter* ue, UnitOrigin unitOrigin,
215 bool usePreAllocatedUnitSn); // nothrow
217 static bool s_deleteLocalOnFailure;
218 // All database table names use the schema ID (sha1 checksum based on the
219 // source code) as a suffix. For example, if the schema ID is
220 // "b02c58478ce89719782fea89f3009295faceb00c", the file magic is stored in the
221 // magic_b02c58478ce89719782fea89f3009295faceb00c table:
223 // CREATE TABLE magic_b02c58478ce89719782fea89f3009295faceb00c(
224 // product[TEXT]);
225 // INSERT INTO magic_b02c58478ce89719782fea89f3009295faceb00c VALUES(
226 // 'facebook.com HipHop Virtual Machine bytecode repository');
228 // This allows multiple schemas to coexist in the same database, which is
229 // especially important if multiple versions of hhvm are in use at the same
230 // time.
231 private:
232 // Magic product constant used to distinguish a .hhbc database.
233 static const char* kMagicProduct;
234 static const char* kDbs[RepoIdCount];
236 void connect();
237 void disconnect() noexcept;
238 void initCentral();
239 RepoStatus openCentral(const char* repoPath, std::string& errorMsg);
240 void initLocal();
241 bool attachLocal(const char* repoPath, bool isWritable);
242 void pragmas(int repoId); // throws(RepoExc)
243 void getIntPragma(int repoId, const char* name, int& val); // throws(RepoExc)
244 void setIntPragma(int repoId, const char* name, int val); // throws(RepoExc)
245 void getTextPragma(int repoId, const char* name, std::string& val);
246 // throws(RepoExc)
247 void setTextPragma(int repoId, const char* name, const char* val);
248 // throws(RepoExc)
249 RepoStatus initSchema(int repoId, bool& isWritable, std::string& errorMsg);
250 bool schemaExists(int repoId);
251 RepoStatus createSchema(int repoId, std::string& errorMsg);
252 bool writable(int repoId);
254 private:
255 static std::string s_cliFile;
256 static GlobalData s_globalData;
258 std::string m_localRepo;
259 std::string m_centralRepo;
260 sqlite3* m_dbc; // Database connection, shared by multiple attached databases.
261 bool m_localReadable;
262 bool m_localWritable;
263 int m_evalRepoId;
264 unsigned m_txDepth; // Transaction nesting depth.
265 bool m_rollback; // If true, rollback rather than commit.
266 RepoStmt m_beginStmt;
267 RepoStmt m_rollbackStmt;
268 RepoStmt m_commitStmt;
269 UnitRepoProxy m_urp;
270 PreClassRepoProxy m_pcrp;
271 RecordRepoProxy m_rrp;
272 FuncRepoProxy m_frp;
273 LitstrRepoProxy m_lsrp;
276 //////////////////////////////////////////////////////////////////////
279 * Try to commit a vector of unit emitters to the current repo. Note that
280 * errors are ignored!
282 void batchCommit(const std::vector<std::unique_ptr<UnitEmitter>>&,
283 bool usePreAllocatedUnitSn);
285 bool batchCommitWithoutRetry(const std::vector<std::unique_ptr<UnitEmitter>>&,
286 bool usePreAllocatedUnitSn);
288 //////////////////////////////////////////////////////////////////////
292 #endif