mirror of https://gitee.com/bigwinds/arangodb
644 lines
20 KiB
C++
644 lines
20 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief V8-vocbase bridge
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2014 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 Dr. Frank Celler
|
|
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
|
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "v8-voccursor.h"
|
|
#include "v8-vocbaseprivate.h"
|
|
#include "VocBase/general-cursor.h"
|
|
#include "Basics/conversions.h"
|
|
#include "V8/v8-conv.h"
|
|
#include "Utils/transactions.h"
|
|
|
|
using namespace std;
|
|
using namespace triagens::basics;
|
|
using namespace triagens::arango;
|
|
using namespace triagens::rest;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- forward declarations
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief wrapped class for general cursors
|
|
///
|
|
/// Layout:
|
|
/// - SLOT_CLASS_TYPE
|
|
/// - SLOT_CLASS
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static int32_t const WRP_GENERAL_CURSOR_TYPE = 3;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- GENERAL CURSORS
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief weak reference callback for general cursors
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void WeakGeneralCursorCallback (v8::Isolate* isolate,
|
|
v8::Persistent<v8::Value> object,
|
|
void* parameter) {
|
|
v8::HandleScope scope; // do not remove, will fail otherwise!!
|
|
|
|
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
|
v8g->_hasDeadObjects = true;
|
|
|
|
TRI_general_cursor_t* cursor = (TRI_general_cursor_t*) parameter;
|
|
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
// decrease the reference-counter for the database
|
|
TRI_ReleaseVocBase(cursor->_vocbase);
|
|
|
|
// dispose and clear the persistent handle
|
|
object.Dispose(isolate);
|
|
object.Clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief stores a general cursor in a V8 object
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
v8::Handle<v8::Value> TRI_WrapGeneralCursor (void* cursor) {
|
|
v8::HandleScope scope;
|
|
v8::TryCatch tryCatch;
|
|
|
|
TRI_ASSERT(cursor != nullptr);
|
|
|
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
|
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(isolate->GetData());
|
|
|
|
v8::Handle<v8::Object> result = v8g->GeneralCursorTempl->NewInstance();
|
|
|
|
if (! result.IsEmpty()) {
|
|
TRI_general_cursor_t* c = (TRI_general_cursor_t*) cursor;
|
|
TRI_UseGeneralCursor(c);
|
|
|
|
// increase the reference-counter for the database
|
|
TRI_UseVocBase(c->_vocbase);
|
|
|
|
v8::Persistent<v8::Value> persistent = v8::Persistent<v8::Value>::New(isolate, v8::External::New(cursor));
|
|
|
|
if (tryCatch.HasCaught()) {
|
|
return scope.Close(v8::Undefined());
|
|
}
|
|
|
|
result->SetInternalField(SLOT_CLASS_TYPE, v8::Integer::New(WRP_GENERAL_CURSOR_TYPE));
|
|
result->SetInternalField(SLOT_CLASS, persistent);
|
|
|
|
persistent.MakeWeak(isolate, cursor, WeakGeneralCursorCallback);
|
|
}
|
|
|
|
return scope.Close(result);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extracts a cursor from a V8 object
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_general_cursor_t* UnwrapGeneralCursor (v8::Handle<v8::Object> cursorObject) {
|
|
return TRI_UnwrapClass<TRI_general_cursor_t>(cursorObject, WRP_GENERAL_CURSOR_TYPE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief generates a general cursor from a list
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_CreateCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
TRI_vocbase_t* vocbase = GetContextVocBase();
|
|
|
|
if (vocbase == nullptr) {
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
|
}
|
|
|
|
if (argv.Length() < 1) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "CREATE_CURSOR(<list>, <doCount>, <batchSize>, <ttl>)");
|
|
}
|
|
|
|
if (! argv[0]->IsArray()) {
|
|
TRI_V8_TYPE_ERROR(scope, "<list> must be a list");
|
|
}
|
|
|
|
// extract objects
|
|
v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(argv[0]);
|
|
TRI_json_t* json = TRI_ObjectToJson(array);
|
|
|
|
if (json == nullptr) {
|
|
TRI_V8_TYPE_ERROR(scope, "cannot convert <list> to JSON");
|
|
}
|
|
|
|
// return number of total records in cursor?
|
|
bool doCount = false;
|
|
|
|
if (argv.Length() >= 2) {
|
|
doCount = TRI_ObjectToBoolean(argv[1]);
|
|
}
|
|
|
|
// maximum number of results to return at once
|
|
uint32_t batchSize = 1000;
|
|
|
|
if (argv.Length() >= 3) {
|
|
int64_t maxValue = TRI_ObjectToInt64(argv[2]);
|
|
|
|
if (maxValue > 0 && maxValue < (int64_t) UINT32_MAX) {
|
|
batchSize = (uint32_t) maxValue;
|
|
}
|
|
}
|
|
|
|
double ttl = 0.0;
|
|
if (argv.Length() >= 4) {
|
|
ttl = TRI_ObjectToDouble(argv[3]);
|
|
}
|
|
|
|
if (ttl <= 0.0) {
|
|
ttl = 30.0; // default ttl
|
|
}
|
|
|
|
// create a cursor
|
|
TRI_general_cursor_result_t* cursorResult = TRI_CreateResultGeneralCursor(json);
|
|
|
|
if (cursorResult == nullptr) {
|
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
|
TRI_V8_EXCEPTION_MEMORY(scope);
|
|
}
|
|
|
|
TRI_general_cursor_t* cursor = TRI_CreateGeneralCursor(vocbase, cursorResult, doCount, batchSize, ttl, nullptr);
|
|
|
|
if (cursor == nullptr) {
|
|
TRI_FreeCursorResult(cursorResult);
|
|
TRI_V8_EXCEPTION_MEMORY(scope);
|
|
}
|
|
|
|
v8::Handle<v8::Value> cursorObject = TRI_WrapGeneralCursor(cursor);
|
|
|
|
if (cursorObject.IsEmpty()) {
|
|
TRI_V8_EXCEPTION_MEMORY(scope);
|
|
}
|
|
|
|
return scope.Close(cursorObject);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys a general cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_DisposeGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "dispose()");
|
|
}
|
|
|
|
bool found = TRI_DropGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
return scope.Close(v8::Boolean::New(found));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the id of a general cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_IdGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "id()");
|
|
}
|
|
|
|
TRI_voc_tick_t id = TRI_IdGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
if (id != 0) {
|
|
return scope.Close(V8TickId(id));
|
|
}
|
|
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the number of results
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_CountGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "count()");
|
|
}
|
|
|
|
size_t length = TRI_CountGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
return scope.Close(v8::Number::New((double) length));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the next result from the general cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_NextGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "next()");
|
|
}
|
|
|
|
v8::Handle<v8::Value> value;
|
|
TRI_general_cursor_t* cursor;
|
|
|
|
cursor = (TRI_general_cursor_t*) TRI_UseGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
if (cursor != 0) {
|
|
bool result = false;
|
|
|
|
TRI_LockGeneralCursor(cursor);
|
|
|
|
if (cursor->_length == 0) {
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
return scope.Close(v8::Undefined());
|
|
}
|
|
|
|
// exceptions must be caught in the following part because we hold an exclusive
|
|
// lock that might otherwise not be freed
|
|
v8::TryCatch tryCatch;
|
|
|
|
try {
|
|
TRI_general_cursor_row_t row = cursor->next(cursor);
|
|
|
|
if (row == 0) {
|
|
value = v8::Undefined();
|
|
}
|
|
else {
|
|
value = TRI_ObjectJson((TRI_json_t*) row);
|
|
result = true;
|
|
}
|
|
}
|
|
catch (...) {
|
|
}
|
|
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
if (result && ! tryCatch.HasCaught()) {
|
|
return scope.Close(value);
|
|
}
|
|
|
|
if (tryCatch.HasCaught()) {
|
|
if (tryCatch.CanContinue()) {
|
|
return scope.Close(v8::ThrowException(tryCatch.Exception()));
|
|
}
|
|
else {
|
|
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
|
v8g->_canceled = true;
|
|
return scope.Close(v8::Undefined());
|
|
}
|
|
}
|
|
}
|
|
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief persist the general cursor for usage in subsequent requests
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_PersistGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "persist()");
|
|
}
|
|
|
|
TRI_vocbase_t* vocbase = GetContextVocBase();
|
|
|
|
TRI_PersistGeneralCursor(vocbase, UnwrapGeneralCursor(argv.Holder()));
|
|
return scope.Close(v8::True());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return all following rows from the cursor in one go
|
|
///
|
|
/// This function constructs multiple rows at once and should be preferred over
|
|
/// hasNext()...next() when iterating over bigger result sets
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_ToArrayGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "toArray()");
|
|
}
|
|
|
|
v8::Handle<v8::Array> rows = v8::Array::New();
|
|
TRI_general_cursor_t* cursor = TRI_UseGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
if (cursor != nullptr) {
|
|
bool result = false;
|
|
|
|
TRI_LockGeneralCursor(cursor);
|
|
|
|
// exceptions must be caught in the following part because we hold an exclusive
|
|
// lock that might otherwise not be freed
|
|
v8::TryCatch tryCatch;
|
|
|
|
try {
|
|
uint32_t max = (uint32_t) cursor->getBatchSize(cursor);
|
|
|
|
for (uint32_t i = 0; i < max; ++i) {
|
|
TRI_general_cursor_row_t row = cursor->next(cursor);
|
|
if (row == nullptr) {
|
|
break;
|
|
}
|
|
rows->Set(i, TRI_ObjectJson((TRI_json_t*) row));
|
|
}
|
|
|
|
result = true;
|
|
}
|
|
catch (...) {
|
|
}
|
|
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
if (result && ! tryCatch.HasCaught()) {
|
|
return scope.Close(rows);
|
|
}
|
|
|
|
if (tryCatch.HasCaught()) {
|
|
if (tryCatch.CanContinue()) {
|
|
return scope.Close(v8::ThrowException(tryCatch.Exception()));
|
|
}
|
|
else {
|
|
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
|
v8g->_canceled = true;
|
|
return scope.Close(v8::Undefined());
|
|
}
|
|
}
|
|
}
|
|
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief alias for toArray()
|
|
/// @deprecated
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_GetRowsGeneralCursor (v8::Arguments const& argv) {
|
|
return JS_ToArrayGeneralCursor(argv);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return max number of results per transfer for cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_GetBatchSizeGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "getBatchSize()");
|
|
}
|
|
|
|
TRI_general_cursor_t* cursor = TRI_UseGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
if (cursor != nullptr) {
|
|
TRI_LockGeneralCursor(cursor);
|
|
uint32_t max = cursor->getBatchSize(cursor);
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
return scope.Close(v8::Number::New((double) max));
|
|
}
|
|
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return extra data for cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_GetExtraGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "getExtra()");
|
|
}
|
|
|
|
TRI_general_cursor_t* cursor = TRI_UseGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
if (cursor != nullptr) {
|
|
TRI_LockGeneralCursor(cursor);
|
|
TRI_json_t* extra = cursor->getExtra(cursor);
|
|
|
|
if (extra != nullptr && extra->_type == TRI_JSON_ARRAY) {
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
return scope.Close(TRI_ObjectJson(extra));
|
|
}
|
|
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
return scope.Close(v8::Undefined());
|
|
}
|
|
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return if count flag was set for cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_HasCountGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "hasCount()");
|
|
}
|
|
|
|
TRI_general_cursor_t* cursor = TRI_UseGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
if (cursor != nullptr) {
|
|
TRI_LockGeneralCursor(cursor);
|
|
bool hasCount = cursor->hasCount(cursor);
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
return scope.Close(hasCount ? v8::True() : v8::False());
|
|
}
|
|
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if the cursor is exhausted
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_HasNextGeneralCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 0) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "hasNext()");
|
|
}
|
|
|
|
TRI_general_cursor_t* cursor = TRI_UseGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
|
|
|
|
if (cursor != nullptr) {
|
|
TRI_LockGeneralCursor(cursor);
|
|
bool hasNext = cursor->hasNext(cursor);
|
|
TRI_UnlockGeneralCursor(cursor);
|
|
TRI_ReleaseGeneralCursor(cursor);
|
|
|
|
return scope.Close(v8::Boolean::New(hasNext));
|
|
}
|
|
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief get a (persistent) cursor by its id
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_Cursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 1) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "CURSOR(<cursor-identifier>)");
|
|
}
|
|
|
|
TRI_vocbase_t* vocbase = GetContextVocBase();
|
|
|
|
if (vocbase == nullptr) {
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
|
}
|
|
|
|
// get the id
|
|
v8::Handle<v8::Value> idArg = argv[0]->ToString();
|
|
|
|
if (! idArg->IsString()) {
|
|
TRI_V8_TYPE_ERROR(scope, "expecting a string for <cursor-identifier>)");
|
|
}
|
|
|
|
const string idString = TRI_ObjectToString(idArg);
|
|
uint64_t id = TRI_UInt64String(idString.c_str());
|
|
|
|
TRI_general_cursor_t* cursor = TRI_FindGeneralCursor(vocbase, (TRI_voc_tick_t) id);
|
|
|
|
if (cursor == nullptr) {
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_CURSOR_NOT_FOUND);
|
|
}
|
|
|
|
v8::Handle<v8::Value> cursorObject = TRI_WrapGeneralCursor(cursor);
|
|
|
|
if (cursorObject.IsEmpty()) {
|
|
TRI_V8_EXCEPTION_MEMORY(scope);
|
|
}
|
|
|
|
return scope.Close(cursorObject);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief delete a (persistent) cursor by its id
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static v8::Handle<v8::Value> JS_DeleteCursor (v8::Arguments const& argv) {
|
|
v8::HandleScope scope;
|
|
|
|
if (argv.Length() != 1) {
|
|
TRI_V8_EXCEPTION_USAGE(scope, "DELETE_CURSOR(<cursor-identifier>)");
|
|
}
|
|
|
|
TRI_vocbase_t* vocbase = GetContextVocBase();
|
|
|
|
if (vocbase == nullptr) {
|
|
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
|
}
|
|
|
|
// get the id
|
|
v8::Handle<v8::Value> idArg = argv[0]->ToString();
|
|
|
|
if (! idArg->IsString()) {
|
|
TRI_V8_TYPE_ERROR(scope, "expecting a string for <cursor-identifier>)");
|
|
}
|
|
|
|
const string idString = TRI_ObjectToString(idArg);
|
|
uint64_t id = TRI_UInt64String(idString.c_str());
|
|
|
|
bool found = TRI_RemoveGeneralCursor(vocbase, id);
|
|
|
|
return scope.Close(v8::Boolean::New(found));
|
|
}
|
|
|
|
|
|
// .............................................................................
|
|
// generate the general cursor template
|
|
// .............................................................................
|
|
void TRI_InitV8cursor (v8::Handle<v8::Context> context,
|
|
TRI_server_t* server,
|
|
TRI_vocbase_t* vocbase,
|
|
JSLoader* loader,
|
|
const size_t threadNumber,
|
|
TRI_v8_global_t* v8g){
|
|
v8::Handle<v8::ObjectTemplate> rt;
|
|
v8::Handle<v8::FunctionTemplate> ft;
|
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
|
ft = v8::FunctionTemplate::New();
|
|
ft->SetClassName(TRI_V8_SYMBOL("ArangoCursor"));
|
|
|
|
rt = ft->InstanceTemplate();
|
|
rt->SetInternalFieldCount(2);
|
|
|
|
TRI_AddMethodVocbase(rt, "count", JS_CountGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "dispose", JS_DisposeGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "getBatchSize", JS_GetBatchSizeGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "getExtra", JS_GetExtraGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "getRows", JS_GetRowsGeneralCursor, true); // DEPRECATED, use toArray
|
|
TRI_AddMethodVocbase(rt, "hasCount", JS_HasCountGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "hasNext", JS_HasNextGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "id", JS_IdGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "next", JS_NextGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "persist", JS_PersistGeneralCursor);
|
|
TRI_AddMethodVocbase(rt, "toArray", JS_ToArrayGeneralCursor);
|
|
|
|
v8g->GeneralCursorTempl = v8::Persistent<v8::ObjectTemplate>::New(isolate, rt);
|
|
TRI_AddGlobalFunctionVocbase(context, "ArangoCursor", ft->GetFunction());
|
|
|
|
// cursor functions. not intended to be used by end users
|
|
TRI_AddGlobalFunctionVocbase(context, "CURSOR", JS_Cursor, true);
|
|
TRI_AddGlobalFunctionVocbase(context, "CREATE_CURSOR", JS_CreateCursor, true);
|
|
TRI_AddGlobalFunctionVocbase(context, "DELETE_CURSOR", JS_DeleteCursor, true);
|
|
}
|