2 +----------------------------------------------------------------------+
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_
29 #include <sys/types.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>
44 ///////////////////////////////////////////////////////////////////////////////
46 struct RepoAutoloadMapBuilder
;
52 struct Repo
: RepoProxy
{
55 // Do not directly instantiate this class; a thread-local creates one per
56 // thread on demand when Repo::get() is called.
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();
73 Repo(const Repo
&) = delete;
74 Repo
& operator=(const Repo
&) = delete;
76 const char* dbName(int repoId
) const {
77 assertx(repoId
< RepoIdCount
);
80 sqlite3
* dbc() const { return m_dbc
; }
81 int repoIdForNewUnit(UnitOrigin unitOrigin
) const {
83 case UnitOrigin::File
:
84 return m_localWritable
? RepoIdLocal
: RepoIdCentral
;
85 case UnitOrigin::Eval
:
92 std::string
repoName(int repoId
) const {
94 case RepoIdLocal
: return m_localRepo
;
95 case RepoIdCentral
: return m_centralRepo
;
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
,
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
122 size_t stringLengthLimit() const;
125 * Return a vector of (filepath, SHA1) for every unit in central
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
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
);
155 * Used during repo creation to associate the supplied GlobalData
156 * with the repo that was being built. Also saves the global litstr
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
);
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
);
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
];
202 std::string
table(int repoId
, const char* tablePrefix
);
203 void exec(const std::string
& sQuery
); // throws(RepoExc)
205 RepoTxn
begin(); // throws(RepoExc)
207 friend struct RepoTxn
;
208 void txPop(); // throws(RepoExc)
209 void rollback(); // nothrow
210 void commit(); // throws(RepoExc)
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(
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
232 // Magic product constant used to distinguish a .hhbc database.
233 static const char* kMagicProduct
;
234 static const char* kDbs
[RepoIdCount
];
237 void disconnect() noexcept
;
239 RepoStatus
openCentral(const char* repoPath
, std::string
& errorMsg
);
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
);
247 void setTextPragma(int repoId
, const char* name
, const char* val
);
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
);
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
;
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
;
270 PreClassRepoProxy m_pcrp
;
271 RecordRepoProxy m_rrp
;
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 //////////////////////////////////////////////////////////////////////