Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/js to cpp transaction handler #2985

Merged
merged 13 commits into from
Aug 11, 2017
Merged
2 changes: 1 addition & 1 deletion UnitTests/HttpInterface/api-transactions-cluster-spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(500)
doc.parsed_response['errorNum'].should eq(500)
doc.parsed_response['errorNum'].should eq(1650)
end
end

Expand Down
106 changes: 52 additions & 54 deletions UnitTests/HttpInterface/api-transactions-noncluster-spec.rb

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions arangod/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ SET(ARANGOD_SOURCES
RestHandler/RestShutdownHandler.cpp
RestHandler/RestSimpleHandler.cpp
RestHandler/RestSimpleQueryHandler.cpp
RestHandler/RestTransactionHandler.cpp
RestHandler/RestUploadHandler.cpp
RestHandler/RestUsersHandler.cpp
RestHandler/RestVersionHandler.cpp
Expand Down Expand Up @@ -381,6 +382,7 @@ SET(ARANGOD_SOURCES
VocBase/Methods/Collections.cpp
VocBase/Methods/Databases.cpp
VocBase/Methods/Indexes.cpp
VocBase/Methods/Transactions.cpp
VocBase/AuthInfo.cpp
VocBase/AuthUserEntry.cpp
VocBase/EdgeCollectionInfo.cpp
Expand Down
19 changes: 16 additions & 3 deletions arangod/GeneralServer/AsyncJobManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "Basics/ReadLocker.h"
#include "Basics/WriteLocker.h"
#include "Basics/voc-errors.h"
#include "GeneralServer/RestHandler.h"
#include "Logger/Logger.h"
#include "Rest/GeneralResponse.h"
Expand Down Expand Up @@ -180,13 +181,18 @@ void AsyncJobManager::deleteExpiredJobResults(double stamp) {
}
}

bool AsyncJobManager::cancelJob(AsyncJobResult::IdType jobId) {
Result AsyncJobManager::cancelJob(AsyncJobResult::IdType jobId) {
Result rv;
WRITE_LOCKER(writeLocker, _lock);

auto it = _jobs.find(jobId);

if (it == _jobs.end()) {
return false;
rv.reset(TRI_ERROR_HTTP_NOT_FOUND
, "could not find job (" + std::to_string(jobId) +
") in AsyncJobManager during cancel operation"
);
return rv;
}

bool ok = true;
Expand All @@ -196,7 +202,14 @@ bool AsyncJobManager::cancelJob(AsyncJobResult::IdType jobId) {
ok = handler->cancel();
}

return ok;
if(!ok){
// if you end up here you might need to implement the cancel method on your handler
rv.reset(TRI_ERROR_INTERNAL
,"could not cancel job (" + std::to_string(jobId) +
") in handler"
);
}
return rv;
}

std::vector<AsyncJobResult::IdType> AsyncJobManager::pending(size_t maxCount) {
Expand Down
3 changes: 2 additions & 1 deletion arangod/GeneralServer/AsyncJobManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define ARANGOD_HTTP_SERVER_ASYNC_JOB_MANAGER_H 1

#include "Basics/Common.h"
#include "Basics/Result.h"
#include "Basics/ReadWriteLock.h"

namespace arangodb {
Expand Down Expand Up @@ -82,7 +83,7 @@ class AsyncJobManager {
bool deleteJobResult(AsyncJobResult::IdType);
void deleteJobResults();
void deleteExpiredJobResults(double stamp);
bool cancelJob(AsyncJobResult::IdType);
Result cancelJob(AsyncJobResult::IdType);

std::vector<AsyncJobResult::IdType> pending(size_t maxCount);
std::vector<AsyncJobResult::IdType> done(size_t maxCount);
Expand Down
4 changes: 4 additions & 0 deletions arangod/GeneralServer/GeneralServerFeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "RestHandler/RestShutdownHandler.h"
#include "RestHandler/RestSimpleHandler.h"
#include "RestHandler/RestSimpleQueryHandler.h"
#include "RestHandler/RestTransactionHandler.h"
#include "RestHandler/RestUploadHandler.h"
#include "RestHandler/RestUsersHandler.h"
#include "RestHandler/RestVersionHandler.h"
Expand Down Expand Up @@ -473,6 +474,9 @@ void GeneralServerFeature::defineHandlers() {

_handlerFactory->addHandler(
"/_api/version", RestHandlerCreator<RestVersionHandler>::createNoData);

_handlerFactory->addHandler(
"/_api/transaction", RestHandlerCreator<RestTransactionHandler>::createNoData);

#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
_handlerFactory->addHandler(
Expand Down
2 changes: 2 additions & 0 deletions arangod/GeneralServer/RestHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class RestHandler : public std::enable_shared_from_this<RestHandler> {
virtual RestStatus execute() = 0;
virtual void finalizeExecute() {}

// you might need to implment this in you handler
// if it will be executed in an async job
virtual bool cancel() {
_canceled.store(true);
return false;
Expand Down
6 changes: 3 additions & 3 deletions arangod/RestHandler/RestJobHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ void RestJobHandler::putJobMethod() {
uint64_t jobId = StringUtils::uint64(value);

if (method == "cancel") {
bool status = _jobManager->cancelJob(jobId);
Result status = _jobManager->cancelJob(jobId);

// unknown or already fetched job
if (!status) {
generateError(rest::ResponseCode::NOT_FOUND, TRI_ERROR_HTTP_NOT_FOUND);
if (status.fail()) {
generateError(status);
} else {
VPackBuilder json;
json.add(VPackValue(VPackValueType::Object));
Expand Down
118 changes: 118 additions & 0 deletions arangod/RestHandler/RestTransactionHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
////////////////////////////////////////////////////////////////////////////////
/// 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 "Basics/WriteLocker.h"
#include "Basics/ReadLocker.h"
#include "RestTransactionHandler.h"

#include "ApplicationFeatures/ApplicationServer.h"
#include "VocBase/Methods/Transactions.h"
#include "Rest/HttpRequest.h"
#include "Basics/voc-errors.h"
#include "V8Server/V8Context.h"
#include "V8Server/V8DealerFeature.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(GeneralResponse::responseCode(TRI_ERROR_BAD_PARAMETER),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(GeneralResponse::responseCode(TRI_ERROR_INTERNAL),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()) {
generateSuccess(rest::ResponseCode::OK, VPackSlice::nullSlice());
} else {
generateSuccess(rest::ResponseCode::OK, slice);
}
} else {
generateError(res);
}
} catch (arangodb::basics::Exception const& ex) {
generateError(GeneralResponse::responseCode(ex.code()),ex.code(), ex.what());
} catch (std::exception const& ex) {
generateError(GeneralResponse::responseCode(TRI_ERROR_INTERNAL), TRI_ERROR_INTERNAL, ex.what());
} catch (...) {
generateError(GeneralResponse::responseCode(TRI_ERROR_INTERNAL), 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;
}
52 changes: 52 additions & 0 deletions arangod/RestHandler/RestTransactionHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
////////////////////////////////////////////////////////////////////////////////
/// 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
////////////////////////////////////////////////////////////////////////////////

#ifndef ARANGOD_REST_HANDLER_REST_TRANSACTION_HANDLER_H
#define ARANGOD_REST_HANDLER_REST_TRANSACTION_HANDLER_H 1

#include "Basics/ReadWriteLock.h"
#include "RestHandler/RestVocbaseBaseHandler.h"

namespace arangodb {

class V8Context;

class RestTransactionHandler : public arangodb::RestVocbaseBaseHandler {
V8Context* _v8Context;
basics::ReadWriteLock _lock;

public:
RestTransactionHandler(GeneralRequest*, GeneralResponse*);

public:
char const* name() const override final { return "RestTransactionHandler"; }
bool isDirect() const override { return false; }
RestStatus execute() override;
bool cancel() override final;

private:
void returnContext();
};
}

#endif
Loading