コード例 #1
0
ファイル: ShellFeature.cpp プロジェクト: JiangKevin/arangodb
void ShellFeature::validateOptions(
    std::shared_ptr<options::ProgramOptions> options) {
  _positionals = options->processingResult()._positionals;

  ClientFeature* client =
      dynamic_cast<ClientFeature*>(server()->feature("Client"));

  ConsoleFeature* console =
      dynamic_cast<ConsoleFeature*>(server()->feature("Console"));

  if (client->endpoint() == "none") {
    client->disable();
  }

  if (!_jslint.empty()) {
    client->disable();
  }

  size_t n = 0;

  _runMode = RunMode::INTERACTIVE;

  if (!_executeScripts.empty()) {
    console->setQuiet(true);
    _runMode = RunMode::EXECUTE_SCRIPT;
    ++n;
  }

  if (!_executeStrings.empty()) {
    console->setQuiet(true);
    _runMode = RunMode::EXECUTE_STRING;
    ++n;
  }

  if (!_checkSyntaxFiles.empty()) {
    console->setQuiet(true);
    _runMode = RunMode::CHECK_SYNTAX;
    ++n;
  }

  if (!_unitTests.empty()) {
    console->setQuiet(true);
    _runMode = RunMode::UNIT_TESTS;
    ++n;
  }

  if (!_jslint.empty()) {
    console->setQuiet(true);
    _runMode = RunMode::JSLINT;
    ++n;
  }

  if (1 < n) {
    LOG(ERR) << "you cannot specify more than one type ("
             << "jslint, execute, execute-string, check-syntax, unit-tests)";
  }
}
コード例 #2
0
// helper to rewrite HTTP location
std::string ArangoClientHelper::rewriteLocation(void* data,
                                                std::string const& location) {
  if (location.compare(0, 5, "/_db/") == 0) {
    return location;
  }

  ClientFeature* client = static_cast<ClientFeature*>(data);
  std::string const& dbname = client->databaseName();

  if (location[0] == '/') {
    return "/_db/" + dbname + location;
  }
  return "/_db/" + dbname + "/" + location;
}
コード例 #3
0
ファイル: V8ShellFeature.cpp プロジェクト: triagens/arangodb
// the result is wrapped in a Javascript variable SYS_ARANGO
V8ClientConnection* V8ShellFeature::setup(
    v8::Local<v8::Context>& context, bool createConnection,
    std::vector<std::string> const& positionals, bool* promptError) {
  std::unique_ptr<V8ClientConnection> v8connection;

  ClientFeature* client = nullptr;

  if (createConnection) {
    client = dynamic_cast<ClientFeature*>(server()->feature("Client"));

    if (client != nullptr && client->isEnabled()) {
      auto connection = client->createConnection();
      v8connection = std::make_unique<V8ClientConnection>(
          connection, client->databaseName(), client->username(),
          client->password(), client->requestTimeout());
    } else {
      client = nullptr;
    }
  }

  initMode(ShellFeature::RunMode::INTERACTIVE, positionals);

  if (createConnection && client != nullptr) {
    v8connection->initServer(_isolate, context, client);
  }

  bool pe = printHello(v8connection.get());
  loadModules(ShellFeature::RunMode::INTERACTIVE);

  if (promptError != nullptr) {
    *promptError = pe;
  }

  return v8connection.release();
}
コード例 #4
0
void RestoreFeature::start() {
  ClientFeature* client = application_features::ApplicationServer::getFeature<ClientFeature>("Client");

  int ret = EXIT_SUCCESS;
  *_result = ret;

  try {
    _httpClient = client->createHttpClient();
  } catch (...) {
    LOG(FATAL) << "cannot create server connection, giving up!";
    FATAL_ERROR_EXIT();
  }

  std::string dbName = client->databaseName();

  _httpClient->setLocationRewriter(static_cast<void*>(client), &rewriteLocation);
  _httpClient->setUserNamePassword("/", client->username(), client->password());

  int err = TRI_ERROR_NO_ERROR;
  std::string versionString = _httpClient->getServerVersion(&err);

  if (_createDatabase && err == TRI_ERROR_ARANGO_DATABASE_NOT_FOUND) {
    // database not found, but database creation requested
    std::cout << "Creating database '" << dbName << "'" << std::endl;

    client->setDatabaseName("_system");

    int res = tryCreateDatabase(client, dbName);

    if (res != TRI_ERROR_NO_ERROR) {
      LOG(ERR) << "Could not create database '" << dbName << "'";
      LOG(FATAL) << _httpClient->getErrorMessage() << "'";
      FATAL_ERROR_EXIT();
    }

    // restore old database name
    client->setDatabaseName(dbName);

    // re-fetch version
    versionString = _httpClient->getServerVersion(nullptr);
  }

  if (!_httpClient->isConnected()) {
    LOG(ERR) << "Could not connect to endpoint "
             << _httpClient->getEndpointSpecification();
    LOG(FATAL) << _httpClient->getErrorMessage() << "'";
    FATAL_ERROR_EXIT();
  }

  // successfully connected
  std::cout << "Server version: " << versionString << std::endl;

  // validate server version
  std::pair<int, int> version = Version::parseVersionString(versionString);

  if (version.first < 3) {
    // we can connect to 3.x
    LOG(ERR) << "got incompatible server version '" << versionString << "'";

    if (!_force) {
      LOG(FATAL) << "giving up!";
      FATAL_ERROR_EXIT();
    }
  }

  // Version 1.4 did not yet have a cluster mode
  _clusterMode = getArangoIsCluster(nullptr);

  if (_progress) {
    std::cout << "# Connected to ArangoDB '"
              << _httpClient->getEndpointSpecification() << "'" << std::endl;
  }

  std::string errorMsg = "";

  int res;
  try {
    res = processInputDirectory(errorMsg);
  } catch (std::exception const& ex) {
    LOG(ERR) << "caught exception " << ex.what();
    res = TRI_ERROR_INTERNAL;
  } catch (...) {
    LOG(ERR) << "Error: caught unknown exception";
    res = TRI_ERROR_INTERNAL;
  }

  if (res != TRI_ERROR_NO_ERROR) {
    if (!errorMsg.empty()) {
      LOG(ERR) << errorMsg;
    } else {
      LOG(ERR) << "An error occurred";
    }
    ret = EXIT_FAILURE;
  }

  if (_progress) {
    if (_importData) {
      std::cout << "Processed " << _stats._totalCollections
                << " collection(s), "
                << "read " << _stats._totalRead << " byte(s) from datafiles, "
                << "sent " << _stats._totalBatches << " batch(es)" << std::endl;
    } else if (_importStructure) {
      std::cout << "Processed " << _stats._totalCollections << " collection(s)"
                << std::endl;
    }
  }
  
  *_result = ret;
}
コード例 #5
0
ファイル: V8ShellFeature.cpp プロジェクト: triagens/arangodb
int V8ShellFeature::runShell(std::vector<std::string> const& positionals) {
  v8::Locker locker{_isolate};

  v8::Isolate::Scope isolate_scope(_isolate);
  v8::HandleScope handle_scope(_isolate);

  v8::Local<v8::Context> context =
      v8::Local<v8::Context>::New(_isolate, _context);

  v8::Context::Scope context_scope{context};

  bool promptError;
  auto v8connection = setup(context, true, positionals, &promptError);
  std::unique_ptr<V8ClientConnection> guard(v8connection);

  V8LineEditor v8LineEditor(_isolate, context, "." + _name + ".history");

  if (v8connection != nullptr) {
    v8LineEditor.setSignalFunction(
        [&v8connection]() { v8connection->setInterrupted(true); });
  }

  v8LineEditor.open(_console->autoComplete());

  v8::Local<v8::String> name(
      TRI_V8_ASCII_STRING2(_isolate, TRI_V8_SHELL_COMMAND_NAME));

  uint64_t nrCommands = 0;

  ClientFeature* client = server()->getFeature<ClientFeature>("Client");

  if (!client->isEnabled()) {
    client = nullptr;
  }

  bool const isBatch = isatty(STDIN_FILENO) == 0;
  bool lastEmpty = isBatch;

  while (true) {
    _console->setPromptError(promptError);
    auto prompt = _console->buildPrompt(client);

    ShellBase::EofType eof = ShellBase::EOF_NONE;
    std::string input =
        v8LineEditor.prompt(prompt._colored, prompt._plain, eof);

    if (eof == ShellBase::EOF_FORCE_ABORT || (eof == ShellBase::EOF_ABORT && lastEmpty)) {
      break;
    }

    if (input.empty()) {
      promptError = false;
      lastEmpty = true;
      continue;
    }
    lastEmpty = isBatch;

    _console->log(prompt._plain + input + "\n");

    std::string i = StringUtils::trim(input);

    if (i == "exit" || i == "quit" || i == "exit;" || i == "quit;") {
      break;
    }

    if (i == "help" || i == "help;") {
      input = "help()";
    }

    v8LineEditor.addHistory(input);

    v8::TryCatch tryCatch;

    _console->startPager();

    // assume the command succeeds
    promptError = false;

    // execute command and register its result in __LAST__
    v8LineEditor.setExecutingCommand(true);

    v8::Handle<v8::Value> v = TRI_ExecuteJavaScriptString(
        _isolate, context, TRI_V8_STRING2(_isolate, input.c_str()), name, true);

    v8LineEditor.setExecutingCommand(false);

    if (v.IsEmpty()) {
      context->Global()->Set(TRI_V8_ASCII_STRING2(_isolate, "_last"),
                             v8::Undefined(_isolate));
    } else {
      context->Global()->Set(TRI_V8_ASCII_STRING2(_isolate, "_last"), v);
    }

    // command failed
    if (tryCatch.HasCaught()) {
      std::string exception;

      if (!tryCatch.CanContinue() || tryCatch.HasTerminated()) {
        exception = "command locally aborted\n";
      } else {
        exception = TRI_StringifyV8Exception(_isolate, &tryCatch);
      }

      _console->printErrorLine(exception);
      _console->log(exception);

      // this will change the prompt for the next round
      promptError = true;
    }

    if (v8connection != nullptr) {
      v8connection->setInterrupted(false);
    }

    _console->stopPager();
    _console->printLine("");

    _console->log("\n");

    // make sure the last command result makes it into the log file
    _console->flushLog();

    // gc
    if (++nrCommands >= _gcInterval ||
        V8PlatformFeature::isOutOfMemory(_isolate)) {
      nrCommands = 0;
      TRI_RunGarbageCollectionV8(_isolate, 500.0);

      // needs to be reset after the garbage collection
      V8PlatformFeature::resetOutOfMemory(_isolate);
    }
  }
      
  if (!_console->quiet()) {
    _console->printLine("");
    _console->printByeBye();
  }

  return promptError ? TRI_ERROR_INTERNAL : TRI_ERROR_NO_ERROR;
}
コード例 #6
0
ファイル: ImportFeature.cpp プロジェクト: triagens/arangodb
void ImportFeature::start() {
  ClientFeature* client = application_features::ApplicationServer::getFeature<ClientFeature>("Client");

  int ret = EXIT_SUCCESS;
  *_result = ret;

  std::unique_ptr<SimpleHttpClient> httpClient;

  try {
    httpClient = client->createHttpClient();
  } catch (...) {
    LOG(FATAL) << "cannot create server connection, giving up!";
    FATAL_ERROR_EXIT();
  }

  httpClient->setLocationRewriter(static_cast<void*>(client), &rewriteLocation);
  httpClient->setUserNamePassword("/", client->username(), client->password());

  // must stay here in order to establish the connection
  httpClient->getServerVersion();

  if (!httpClient->isConnected()) {
    LOG(ERR) << "Could not connect to endpoint '" << client->endpoint()
             << "', database: '" << client->databaseName() << "', username: '******'";
    LOG(FATAL) << httpClient->getErrorMessage() << "'";
    FATAL_ERROR_EXIT();
  }

  // successfully connected
  std::cout << "Connected to ArangoDB '"
            << httpClient->getEndpointSpecification() << "', version "
            << httpClient->getServerVersion() << ", database: '"
            << client->databaseName() << "', username: '******'" << std::endl;

  std::cout << "----------------------------------------" << std::endl;
  std::cout << "database:               " << client->databaseName() << std::endl;
  std::cout << "collection:             " << _collectionName << std::endl;
  if (!_fromCollectionPrefix.empty()) {
    std::cout << "from collection prefix: " << _fromCollectionPrefix << std::endl;
  }
  if (!_toCollectionPrefix.empty()) {
    std::cout << "to collection prefix:   " << _toCollectionPrefix << std::endl;
  }
  std::cout << "create:                 " << (_createCollection ? "yes" : "no")
            << std::endl;
  std::cout << "source filename:        " << _filename << std::endl;
  std::cout << "file type:              " << _typeImport << std::endl;

  if (_typeImport == "csv") {
    std::cout << "quote:                  " << _quote << std::endl;
  } 
  if (_typeImport == "csv" || _typeImport == "tsv") {
    std::cout << "separator:              " << _separator << std::endl;
  }

  std::cout << "connect timeout:        " << client->connectionTimeout() << std::endl;
  std::cout << "request timeout:        " << client->requestTimeout() << std::endl;
  std::cout << "----------------------------------------" << std::endl;

  arangodb::import::ImportHelper ih(httpClient.get(), _chunkSize);

  // create colletion
  if (_createCollection) {
    ih.setCreateCollection(true);
  }

  if (_createCollectionType == "document" || _createCollectionType == "edge") {
    ih.setCreateCollectionType(_createCollectionType);
  }

  ih.setConversion(_convert);
  ih.setRowsToSkip(static_cast<size_t>(_rowsToSkip));
  ih.setOverwrite(_overwrite);
  ih.useBackslash(_useBackslash);

  // quote
  if (_quote.length() <= 1) {
    ih.setQuote(_quote);
  } else {
    LOG(FATAL) << "Wrong length of quote character.";
    FATAL_ERROR_EXIT();
  }

  if (_separator.empty()) {
    _separator = ",";
    if (_typeImport == "tsv") {
      _separator = "\\t";
    }
  }

  // separator
  if (_separator.length() == 1 || _separator == "\\r" || _separator == "\\n" || _separator == "\\t") {
    ih.setSeparator(_separator);
  } else {
    LOG(FATAL) << "_separator must be exactly one character.";
    FATAL_ERROR_EXIT();
  }

  // collection name
  if (_collectionName == "") {
    LOG(FATAL) << "Collection name is missing.";
    FATAL_ERROR_EXIT();
  }

  // filename
  if (_filename == "") {
    LOG(FATAL) << "File name is missing.";
    FATAL_ERROR_EXIT();
  }

  if (_filename != "-" && !FileUtils::isRegularFile(_filename)) {
    if (!FileUtils::exists(_filename)) {
      LOG(FATAL) << "Cannot open file '" << _filename << "'. File not found.";
    } else if (FileUtils::isDirectory(_filename)) {
      LOG(FATAL) << "Specified file '" << _filename
                 << "' is a directory. Please use a regular file.";
    } else {
      LOG(FATAL) << "Cannot open '" << _filename << "'. Invalid file type.";
    }

    FATAL_ERROR_EXIT();
  }

  // progress
  if (_progress) {
    ih.setProgress(true);
  }

  if (_onDuplicateAction != "error" && _onDuplicateAction != "update" &&
      _onDuplicateAction != "replace" && _onDuplicateAction != "ignore") {
    LOG(FATAL)
        << "Invalid value for '--on-duplicate'. Possible values: 'error', "
           "'update', 'replace', 'ignore'.";
    FATAL_ERROR_EXIT();
  }

  ih.setOnDuplicateAction(_onDuplicateAction);

  try {
    bool ok = false;
    // set prefixes
    ih.setFrom(_fromCollectionPrefix);
    ih.setTo(_toCollectionPrefix);

    // import type
    if (_typeImport == "csv") {
      std::cout << "Starting CSV import..." << std::endl;
      ok = ih.importDelimited(_collectionName, _filename,
                              arangodb::import::ImportHelper::CSV);
    }

    else if (_typeImport == "tsv") {
      std::cout << "Starting TSV import..." << std::endl;
      ih.setQuote("");
      ok = ih.importDelimited(_collectionName, _filename,
                              arangodb::import::ImportHelper::TSV);
    }

    else if (_typeImport == "json") {
      std::cout << "Starting JSON import..." << std::endl;
      ok = ih.importJson(_collectionName, _filename);
    }

    else {
      LOG(FATAL) << "Wrong type '" << _typeImport << "'.";
      FATAL_ERROR_EXIT();
    }

    std::cout << std::endl;

    // give information about import
    if (ok) {
      std::cout << "created:          " << ih.getNumberCreated() << std::endl;
      std::cout << "warnings/errors:  " << ih.getNumberErrors() << std::endl;
      std::cout << "updated/replaced: " << ih.getNumberUpdated() << std::endl;
      std::cout << "ignored:          " << ih.getNumberIgnored() << std::endl;

      if (_typeImport == "csv" || _typeImport == "tsv") {
        std::cout << "lines read:       " << ih.getReadLines() << std::endl;
      }

    } else {
      LOG(ERR) << "error message:    " << ih.getErrorMessage();
    }
  } catch (std::exception const& ex) {
    LOG(ERR) << "Caught exception " << ex.what() << " during import";
  } catch (...) {
    LOG(ERR) << "Got an unknown exception during import";
  }

  *_result = ret;
}