1
0
Fork 0
arangodb/arangod/RestHandler/RestTransactionHandler.cpp

117 lines
3.6 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Christoph Uhde
////////////////////////////////////////////////////////////////////////////////
#include "RestTransactionHandler.h"
#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/ReadLocker.h"
#include "Basics/WriteLocker.h"
#include "Cluster/ServerState.h"
#include "Rest/HttpRequest.h"
#include "V8Server/V8Context.h"
#include "V8Server/V8DealerFeature.h"
#include "VocBase/Methods/Transactions.h"
#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::rest;
RestTransactionHandler::RestTransactionHandler(GeneralRequest* request, GeneralResponse* response)
: RestVocbaseBaseHandler(request, response), _v8Context(nullptr), _lock() {}
void RestTransactionHandler::returnContext() {
WRITE_LOCKER(writeLock, _lock);
V8DealerFeature::DEALER->exitContext(_v8Context);
_v8Context = nullptr;
}
RestStatus RestTransactionHandler::execute() {
if (_request->requestType() != rest::RequestType::POST) {
generateError(rest::ResponseCode::METHOD_NOT_ALLOWED, 405);
return RestStatus::DONE;
}
auto slice = _request->payload();
if (!slice.isObject()) {
generateError(
Result(TRI_ERROR_BAD_PARAMETER, "could not acquire v8 context"));
return RestStatus::DONE;
}
std::string portType = _request->connectionInfo().portType();
_v8Context = V8DealerFeature::DEALER->enterContext(&_vocbase, true /*allow use database*/);
if (!_v8Context) {
generateError(Result(TRI_ERROR_INTERNAL, "could not acquire v8 context"));
return RestStatus::DONE;
}
TRI_DEFER(returnContext());
VPackBuilder result;
try {
{
WRITE_LOCKER(lock, _lock);
if (_canceled) {
generateCanceled();
return RestStatus::DONE;
}
}
Result res = executeTransaction(_v8Context->_isolate, _lock, _canceled,
slice, portType, result);
if (res.ok()) {
VPackSlice slice = result.slice();
if (slice.isNone()) {
generateOk(rest::ResponseCode::OK, VPackSlice::nullSlice());
} else {
generateOk(rest::ResponseCode::OK, slice);
}
} else {
generateError(res);
}
} catch (arangodb::basics::Exception const& ex) {
generateError(Result(ex.code(), ex.what()));
} catch (std::exception const& ex) {
generateError(Result(TRI_ERROR_INTERNAL, ex.what()));
} catch (...) {
generateError(Result(TRI_ERROR_INTERNAL));
}
return RestStatus::DONE;
}
bool RestTransactionHandler::cancel() {
// cancel v8 transaction
WRITE_LOCKER(writeLock, _lock);
_canceled.store(true);
auto isolate = _v8Context->_isolate;
if (!v8::V8::IsExecutionTerminating(isolate)) {
v8::V8::TerminateExecution(isolate);
}
return true;
}