8000 Merge branch 'feature-3.3/copy-installation-files' of https://github.… · mnemosdev/arangodb@f391771 · GitHub
[go: up one dir, main page]

Skip to content

Commit f391771

Browse files
committed
Merge branch 'feature-3.3/copy-installation-files' of https://github.com/arangodb/arangodb into 3.3
2 parents aa137f1 + eb0fb25 commit f391771

File tree

10 files changed

+164
-10
lines changed

10 files changed

+164
-10
lines changed

arangod/Cluster/v8-cluster.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1883,7 +1883,6 @@ static void JS_Drop(v8::FunctionCallbackInfo<v8::Value> const& args) {
18831883

18841884
static void JS_GetId(v8::FunctionCallbackInfo<v8::Value> const& args) {
18851885
TRI_V8_TRY_CATCH_BEGIN(isolate);
1886-
ONLY_IN_CLUSTER
18871886

18881887
if (args.Length() != 0) {
18891888
TRI_V8_THROW_EXCEPTION_USAGE("getId()");

arangod/RestServer/DatabasePathFeature.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ using namespace arangodb::basics;
3737
using namespace arangodb::options;
3838

3939
DatabasePathFeature::DatabasePathFeature(ApplicationServer* server)
40-
: ApplicationFeature(server, "DatabasePath"),
40+
: ApplicationFeature(server, DatabasePathFeature::name()),
4141
_requiredDirectoryState("any") {
4242
setOptional(false);
4343
requiresElevatedPrivileges(false);

arangod/RestServer/DatabasePathFeature.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ class DatabasePathFeature final
3232
public:
3333
explicit DatabasePathFeature(
3434
application_features::ApplicationServer* server);
35+
36+
static constexpr const char* name() {
37+
return "DatabasePath";
38+
}
3539

3640
public:
3741
void collectOptions(std::shared_ptr<options::ProgramOptions>) override final;

arangod/V8Server/V8DealerFeature.cpp

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "ProgramOptions/Section.h"
4141
#include "Random/RandomGenerator.h"
4242
#include "RestServer/DatabaseFeature.h"
43+
#include "RestServer/DatabasePathFeature.h"
4344
#include "Scheduler/JobGuard.h"
4445
#include "Scheduler/SchedulerFeature.h"
4546
#include "Transaction/V8Context.h"
@@ -95,6 +96,7 @@ V8DealerFeature::V8DealerFeature(
9596
_gcFrequency(30.0),
9697
_gcInterval(1000),
9798
_maxContextAge(60.0),
99+
_copyInstallation(false),
98100
_nrMaxContexts(0),
99101
_nrMinContexts(0),
100102
_nrInflightContexts(0),
@@ -141,6 +143,11 @@ void V8DealerFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
141143
"--javascript.module-directory",
142144
"additional paths containing JavaScript modules",
143145
new VectorParameter<StringParameter>(&_moduleDirectory));
146+
147+
options->addOption(
148+
"--javascript.copy-installation",
149+
"copy contents of 'javascript.startup-directory' on first start",
150+
new BooleanParameter(&_copyInstallation));
144151

145152
options->addOption(
146153
"--javascript.v8-contexts",
@@ -187,9 +194,6 @@ void V8DealerFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
187194
ctx->normalizePath(_startupDirectory, "javascript.startup-directory", true);
188195
ctx->normalizePath(_moduleDirectory, "javascript.module-directory", false);
189196

190-
_startupLoader.setDirectory(_startupDirectory);
191-
ServerState::instance()->setJavaScriptPath(_startupDirectory);
192-
193197
// check whether app-path was specified
194198
if (_appPath.empty()) {
195199
LOG_TOPIC(FATAL, arangodb::Logger::V8) << "no value has been specified for --javascript.app-path";
@@ -207,6 +211,15 @@ void V8DealerFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
207211
}
208212

209213
void V8DealerFeature::start() {
214+
if (_copyInstallation) {
215+
copyInstallationFiles(); // will exit process if it fails
216+
}
217+
LOG_TOPIC(DEBUG, Logger::V8) << "effective startup-directory is '" << _startupDirectory <<
218+
"', effective module-directory is " << _moduleDirectory;
219+
220+
_startupLoader.setDirectory(_startupDirectory);
221+
ServerState::instance()->setJavaScriptPath(_startupDirectory);
222+
210223
// dump paths
211224
{
212225
std::vector<std::string> paths;
@@ -307,6 +320,69 @@ void V8DealerFeature::start() {
307320
startGarbageCollection();
308321
}
309322

323+
void V8DealerFeature::copyInstallationFiles() {
324+
// get base path from DatabasePathFeature
325+
auto dbPathFeature = application_features::ApplicationServer::getFeature<DatabasePathFeature>(DatabasePathFeature::name());
326+
const std::string copyJSPath = FileUtils::buildFilename(dbPathFeature->directory(), "js");
327+
if (copyJSPath == _startupDirectory) {
328+
LOG_TOPIC(FATAL, arangodb::Logger::V8)
329+
<< "'javascript.startup-directory' cannot be inside 'database.directory'";
330+
FATAL_ERROR_EXIT();
331+
}
332+
TRI_ASSERT(!copyJSPath.empty());
333+
334+
const std::string checksumFile = FileUtils::buildFilename(_startupDirectory, StaticStrings::checksumFileJs);
335+
const std::string copyChecksumFile = FileUtils::buildFilename(copyJSPath, StaticStrings::checksumFileJs);
336+
337+
bool overwriteCopy = false;
338+
if (!FileUtils::exists(copyJSPath) ||
339+
!FileUtils::exists(checksumFile) ||
340+
!FileUtils::exists(copyChecksumFile)) {
341+
overwriteCopy = true;
342+
} else {
343+
try {
344+
overwriteCopy = (FileUtils::slurp(copyChecksumFile) != FileUtils::slurp(checksumFile));
345+
} catch(basics::Exception const& e) {
346+
LOG_TOPIC(ERR, Logger::V8) << "Error reading '" << StaticStrings::checksumFileJs <<
347+
"' from disk: " << e.what();
348+
overwriteCopy = true;
349+
}
350+
}
351+
352+
if (overwriteCopy) {
353+
// sanity check before removing an existing directory:
354+
// check if for some reason we will be trying to remove the entire database directory...
355+
if (FileUtils::exists(FileUtils::buildFilename(copyJSPath, "ENGINE"))) {
356+
LOG_TOPIC(FATAL, Logger::V8) << "JS installation path '" << copyJSPath
357+
<< "' seems to be invalid";
358+
FATAL_ERROR_EXIT();
359+
}
360+
361+
LOG_TOPIC(DEBUG, Logger::V8) << "Copying JS installation files to '" << copyJSPath << "'";
362+
int res = TRI_ERROR_NO_ERROR;
363+
if (FileUtils::exists(copyJSPath)) {
364+
res = TRI_RemoveDirectory(copyJSPath.c_str());
365+
if (res != TRI_ERROR_NO_ERROR) {
366+
LOG_TOPIC(FATAL, Logger::V8) << "Error cleaning JS installation path '" << copyJSPath
367+
<< "': " << TRI_errno_string(res);
368+
FATAL_ERROR_EXIT();
369+
}
370+
}
371+
if (!FileUtils::createDirectory(copyJSPath, &res)) {
372+
LOG_TOPIC(FATAL, Logger::V8) << "Error creating JS installation path '" << copyJSPath
373+
<< "': " << TRI_errno_string(res);
374+
FATAL_ERROR_EXIT();
375+
}
376+
std::string error;
377+
if (!FileUtils::copyRecursive(_startupDirectory, copyJSPath, error)) {
378+
LOG_TOPIC(FATAL, Logger::V8) << "Error copying JS installation files to '" << copyJSPath
379+
<< "': " << error;
380+
FATAL_ERROR_EXIT();
381+
}
382+
}
383+
_startupDirectory = copyJSPath;
384+
}
385+
310386
V8Context* V8DealerFeature::addContext() {
311387
V8Context* context = buildContext(nextId());
312388

arangod/V8Server/V8DealerFeature.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class V8DealerFeature final : public application_features::ApplicationFeature {
6767
std::string _appPath;
6868
std::string _startupDirectory;
6969
std::vector<std::string> _moduleDirectory;
70+
bool _copyInstallation;
7071
uint64_t _nrMaxContexts; // maximum number of contexts to create
7172
uint64_t _nrMinContexts; // minimum number of contexts to keep
7273
uint64_t _nrInflightContexts; // number of contexts currently in creation
@@ -127,6 +128,7 @@ class V8DealerFeature final : public application_features::ApplicationFeature {
127128

128129
private:
129130
uint64_t nextId() { return _nextId++; }
131+
void copyInstallationFiles();
130132
V8Context* addContext();
131133
V8Context* buildContext(size_t id);
132134
V8Context* pickFreeContextForGc();

arangosh/Shell/V8ShellFeature.cpp

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "Logger/Logger.h"
3333
#include "ProgramOptions/ProgramOptions.h"
3434
#include "ProgramOptions/Section.h"
35+
#include "Random/RandomGenerator.h"
3536
#include "Rest/HttpResponse.h"
3637
#include "Rest/Version.h"
3738
#include "Shell/ClientFeature.h"
@@ -62,6 +63,8 @@ V8ShellFeature::V8ShellFeature(application_features::ApplicationServer* server,
6263
_startupDirectory("js"),
6364
_clientModule(DEFAULT_CLIENT_MODULE),
6465
_currentModuleDirectory(true),
66+
_copyInstallation(false),
67+
_removeCopyInstallation(false),
6568
_gcInterval(50),
6669
_name(name),
6770
_isolate(nullptr),
@@ -72,6 +75,7 @@ V8ShellFeature::V8ShellFeature(application_features::ApplicationServer* server,
7275
startsAfter("Logger");
7376
startsAfter("Console");
7477
startsAfter("V8Platform");
78+
startsAfter( 179B "Random");
7579
}
7680

7781
void V8ShellFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
@@ -84,6 +88,11 @@ void V8ShellFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
8488
options->addHiddenOption("--javascript.client-module",
8589
"client module to use at startup",
8690
new StringParameter(&_clientModule));
91+
92+
options->addOption("--javascript.copy-directory",
93+
"target directory to copy files from 'javascript.startup-directory' into "
94+
"(only used when `--javascript.copy-installation` is enabled)",
95+
new StringParameter(&_copyDirectory));
8796

8897
options->addHiddenOption(
8998
"--javascript.module-directory",
@@ -93,10 +102,14 @@ void V8ShellFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
93102
options->addOption("--javascript.current-module-directory",
94103
"add current directory to module path",
95104
new BooleanParameter(&_currentModuleDirectory));
105+
106+
options->addOption("--javascript.copy-installation",
107+
"copy contents of 'javascript.startup-directory'",
108+
new BooleanParameter(&_copyInstallation));
96109

97110
options->addOption(
98111
"--javascript.gc-interval",
99-
"request-based garbage collection interval (each n.th commands)",
112+
"request-based garbage collection interval (each n.th command)",
100113
new UInt64Parameter(&_gcInterval));
101114
}
102115

@@ -107,10 +120,7 @@ void V8ShellFeature::validateOptions(
107120
<< "no 'javascript.startup-directory' has been supplied, giving up";
108121
FATAL_ERROR_EXIT();
109122
}
110-
111-
LOG_TOPIC(DEBUG, Logger::V8)
112-
<< "using Javascript startup files at '" << _startupDirectory << "'";
113-
123+
114124
if (!_moduleDirectory.empty()) {
115125
LOG_TOPIC(DEBUG, Logger::V8)
116126
<< "using Javascript modules at '"
@@ -125,6 +135,13 @@ void V8ShellFeature::start() {
125135
auto platform =
126136
application_features::ApplicationServer::getFeature<V8PlatformFeature>(
127137
"V8Platform");
138+
139+
if (_copyInstallation) {
140+
copyInstallationFiles(); // will exit process on error
141+
}
142+
143+
LOG_TOPIC(DEBUG, Logger::V8)
144+
<< "using Javascript startup files at '" << _startupDirectory << "'";
128145

129146
_isolate = platform->createIsolate();
130147

@@ -202,6 +219,50 @@ void V8ShellFeature::unprepare() {
202219
TRI_AllowMemoryFailures();
203220
}
204221

222+
void V8ShellFeature::stop() {
223+
if (_removeCopyInstallation && !_copyDirectory.empty()) {
224+
int res = TRI_RemoveDirectory(_copyDirectory.c_str());
225+
if (res != TRI_ERROR_NO_ERROR) {
226+
LOG_TOPIC(DEBUG, Logger::V8) << "could not cleanup installation file copy in path '" << _copyDirectory << "': " << TRI_errno_string(res);
227+
}
228+
}
229+
}
230+
231+
void V8ShellFeature::copyInstallationFiles() {
232+
if (_copyDirectory.empty()) {
233+
uint64_t r = RandomGenerator::interval(UINT64_MAX);
234+
char buf[sizeof(uint64_t) * 2 + 1];
235+
auto len = TRI_StringUInt64HexInPlace(r, buf);
236+
std::string name("arangosh-js-");
237+
name.append(buf, len);
238+
_copyDirectory = FileUtils::buildFilename(TRI_GetTempPath(), name);
239+
_removeCopyInstallation = true;
240+
}
241+
242+
LOG_TOPIC(DEBUG, Logger::V8) << "Copying JS installation files to '" << _copyDirectory << "'";
243+
int res = TRI_ERROR_NO_ERROR;
244+
if (FileUtils::exists(_copyDirectory)) {
245+
res = TRI_RemoveDirectory(_copyDirectory.c_str());
246+
if (res != TRI_ERROR_NO_ERROR) {
247+
LOG_TOPIC(FATAL, Logger::V8) << "Error cleaning JS installation path '" << _copyDirectory
248+
<< "': " << TRI_errno_string(res);
249+
FATAL_ERROR_EXIT();
250+
}
251+
}
252+
if (!FileUtils::createDirectory(_copyDirectory, &res)) {
253+
LOG_TOPIC(FATAL, Logger::V8) << "Error creating JS installation path '" << _copyDirectory
254+
<< "': " << TRI_errno_string(res);
255+
FATAL_ERROR_EXIT();
256+
}
257+
std::string error;
258+
if (!FileUtils::copyRecursive(_startupDirectory, _copyDirectory, error)) {
259+
LOG_TOPIC(FATAL, Logger::V8) << "Error copying JS installation files to '" << _copyDirectory
260+
<< "': " << error;
261+
FATAL_ERROR_EXIT();
262+
}
263+
_startupDirectory = _copyDirectory;
264+
}
265+
205266
bool V8ShellFeature::printHello(V8ClientConnection* v8connection) {
206267
bool promptError = false;
207268

arangosh/Shell/V8ShellFeature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class V8ShellFeature final : public application_features::ApplicationFeature {
4646
std::shared_ptr<options::ProgramOptions> options) override;
4747
void start() override final;
4848
void unprepare() override final;
49+
void stop() override final;
4950

5051
std::string const& startupDirectory() {
5152
return _startupDirectory;
@@ -54,8 +55,11 @@ class V8ShellFeature final : public application_features::ApplicationFeature {
5455
private:
5556
std::string _startupDirectory;
5657
std::string _clientModule;
58+
std::string _copyDirectory;
5759
std::vector<std::string> _moduleDirectory;
5860
bool _currentModuleDirectory;
61+
bool _copyInstallation;
62+
bool _removeCopyInstallation;
5963
uint64_t _gcInterval;
6064

6165
public:
@@ -69,6 +73,7 @@ class V8ShellFeature final : public application_features::ApplicationFeature {
6973
bool jslint(std::vector<std::string> const& files);
7074

7175
private:
76+
void copyInstallationFiles();
7277
bool printHello(V8ClientConnection*);
7378
void initGlobals();
7479
void initMode(ShellFeature::RunMode, std::vector<std::string> const&);

js/client/modules/@arangodb/process-utils.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ function makeArgsArangod (options, appDir, role, tmpDir) {
363363
'define': 'TOP_DIR=' + TOP_DIR,
364364
'wal.flush-timeout': options.walFlushTimeout,
365365
'javascript.app-path': appDir,
366+
'javascript.copy-installation': false,
366367
'http.trusted-origin': options.httpTrustedOrigin || 'all',
367368
'cluster.create-waits-for-sync-replication': false,
368369
'temp.path': tmpDir

lib/Basics/StaticStrings.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,6 @@ std::string const StaticStrings::MimeTypeJson(
124124
"application/json; charset=utf-8");
125125
std::string const StaticStrings::MimeTypeText("text/plain; charset=utf-8");
126126
std::string const StaticStrings::MimeTypeVPack("application/x-velocypack");
127+
128+
// misc strings
129+
std::string const StaticStrings::checksumFileJs("JS_SHA1SUM.txt");

lib/Basics/StaticStrings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ class StaticStrings {
117117
static std::string const MimeTypeJson;
118118
static std::string const MimeTypeText;
119119
static std::string const MimeTypeVPack;
120+
121+
// misc strings
122+
static std::string const checksumFileJs;
120123
};
121124
}
122125

0 commit comments

Comments
 (0)
0