diff --git a/3rdParty/velocypack/include/velocypack/Iterator.h b/3rdParty/velocypack/include/velocypack/Iterator.h index a60fb9c9db..d6ae121c40 100644 --- a/3rdParty/velocypack/include/velocypack/Iterator.h +++ b/3rdParty/velocypack/include/velocypack/Iterator.h @@ -48,7 +48,7 @@ class ArrayIterator { throw Exception(Exception::InvalidValueType, "Expecting Array slice"); } - if (slice.length() > 0) { + if (_size > 0) { auto h = slice.head(); if (h == 0x13) { _current = slice.at(0).start(); @@ -162,7 +162,7 @@ class ObjectIterator { throw Exception(Exception::InvalidValueType, "Expecting Object slice"); } - if (slice.length() > 0) { + if (_size > 0) { auto h = slice.head(); if (h == 0x14) { _current = slice.keyAt(0, false).start(); diff --git a/arangod/RestHandler/RestCursorHandler.cpp b/arangod/RestHandler/RestCursorHandler.cpp index 926322cdf7..80d0786d73 100644 --- a/arangod/RestHandler/RestCursorHandler.cpp +++ b/arangod/RestHandler/RestCursorHandler.cpp @@ -27,12 +27,12 @@ #include "Basics/Exceptions.h" #include "Basics/MutexLocker.h" #include "Basics/StaticStrings.h" +#include "Basics/VelocyPackDumper.h" #include "Basics/VelocyPackHelper.h" #include "Basics/VPackStringBufferAdapter.h" #include "Utils/Cursor.h" #include "Utils/CursorRepository.h" -#include #include #include #include @@ -176,9 +176,7 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } - arangodb::basics::VPackStringBufferAdapter bufferAdapter( - _response->body().stringBuffer()); - VPackDumper dumper(&bufferAdapter, queryResult.context->getVPackOptions()); + arangodb::basics::VelocyPackDumper dumper(&(_response->body()), queryResult.context->getVPackOptions()); dumper.dump(result.slice()); return; } diff --git a/arangod/Utils/Cursor.cpp b/arangod/Utils/Cursor.cpp index 51c81bd014..9eaa639809 100644 --- a/arangod/Utils/Cursor.cpp +++ b/arangod/Utils/Cursor.cpp @@ -22,6 +22,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "Cursor.h" +#include "Basics/VelocyPackDumper.h" #include "Basics/VelocyPackHelper.h" #include "Basics/VPackStringBufferAdapter.h" #include "Utils/CollectionExport.h" @@ -69,15 +70,13 @@ VelocyPackCursor::VelocyPackCursor(TRI_vocbase_t* vocbase, CursorId id, : Cursor(id, batchSize, extra, ttl, hasCount), _vocbase(vocbase), _result(std::move(result)), - _size(_result.result->slice().length()), + _iterator(_result.result->slice(), true), _cached(_result.cached) { TRI_ASSERT(_result.result->slice().isArray()); TRI_UseVocBase(vocbase); } VelocyPackCursor::~VelocyPackCursor() { - freeJson(); - TRI_ReleaseVocBase(_vocbase); } @@ -86,11 +85,11 @@ VelocyPackCursor::~VelocyPackCursor() { //////////////////////////////////////////////////////////////////////////////// bool VelocyPackCursor::hasNext() { - if (_position < _size) { + if (_iterator.valid()) { return true; } - freeJson(); + _isDeleted = true; return false; } @@ -100,16 +99,17 @@ bool VelocyPackCursor::hasNext() { VPackSlice VelocyPackCursor::next() { TRI_ASSERT(_result.result != nullptr); - TRI_ASSERT(_position < _size); - VPackSlice slice = _result.result->slice(); - return slice.at(_position++); + TRI_ASSERT(_iterator.valid()); + VPackSlice slice = _iterator.value(); + _iterator.next(); + return slice; } //////////////////////////////////////////////////////////////////////////////// /// @brief return the cursor size //////////////////////////////////////////////////////////////////////////////// -size_t VelocyPackCursor::count() const { return _size; } +size_t VelocyPackCursor::count() const { return _iterator.size(); } //////////////////////////////////////////////////////////////////////////////// /// @brief dump the cursor contents into a string buffer @@ -124,39 +124,45 @@ void VelocyPackCursor::dump(arangodb::basics::StringBuffer& buffer) { // if the specified batch size does not get out of hand // otherwise specifying a very high batch size would make the allocation fail // in every case, even if there were much less documents in the collection - auto transactionContext = std::make_shared(_vocbase); + size_t num = n; + if (num == 0) { + num = 1; + } else if (num >= 50000) { + num = 50000; + } + int res = buffer.reserve(num * 48); - if (n <= 50000) { - int res = buffer.reserve(n * 48); - - if (res != TRI_ERROR_NO_ERROR) { - THROW_ARANGO_EXCEPTION(res); - } + if (res != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(res); } - arangodb::basics::VPackStringBufferAdapter bufferAdapter( - buffer.stringBuffer()); - VPackDumper dumper(&bufferAdapter, transactionContext->getVPackOptions()); - for (size_t i = 0; i < n; ++i) { - if (!hasNext()) { - break; - } + arangodb::basics::VelocyPackDumper dumper(&buffer, _result.context->getVPackOptions()); - if (i > 0) { - buffer.appendChar(','); - } + try { - auto row = next(); - if (row.isNone()) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } + for (size_t i = 0; i < n; ++i) { + if (!hasNext()) { + break; + } + + if (i > 0) { + buffer.appendChar(','); + } + + auto row = next(); + + if (row.isNone()) { + THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); + } - try { dumper.dump(row); - } catch (...) { - /// TODO correct error Handling! - THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); } + } catch (arangodb::basics::Exception const& ex) { + THROW_ARANGO_EXCEPTION_MESSAGE(ex.code(), ex.what()); + } catch (std::exception const& ex) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, ex.what()); + } catch (...) { + THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); } buffer.appendText("],\"hasMore\":"); @@ -177,9 +183,6 @@ void VelocyPackCursor::dump(arangodb::basics::StringBuffer& buffer) { VPackSlice const extraSlice = extra(); if (extraSlice.isObject()) { - arangodb::basics::VPackStringBufferAdapter bufferAdapter( - buffer.stringBuffer()); - VPackDumper dumper(&bufferAdapter); buffer.appendText(",\"extra\":"); dumper.dump(extraSlice); } @@ -193,14 +196,6 @@ void VelocyPackCursor::dump(arangodb::basics::StringBuffer& buffer) { } } -//////////////////////////////////////////////////////////////////////////////// -/// @brief free the internals -//////////////////////////////////////////////////////////////////////////////// - -void VelocyPackCursor::freeJson() { - _isDeleted = true; -} - ExportCursor::ExportCursor(TRI_vocbase_t* vocbase, CursorId id, arangodb::CollectionExport* ex, size_t batchSize, double ttl, bool hasCount) diff --git a/arangod/Utils/Cursor.h b/arangod/Utils/Cursor.h index 4b9a25749e..d88e3e0d97 100644 --- a/arangod/Utils/Cursor.h +++ b/arangod/Utils/Cursor.h @@ -29,6 +29,8 @@ #include "Aql/QueryResult.h" #include "VocBase/voc-types.h" +#include + struct TRI_vocbase_t; namespace arangodb { @@ -125,13 +127,10 @@ class VelocyPackCursor : public Cursor { void dump(arangodb::basics::StringBuffer&) override final; - private: - void freeJson(); - private: TRI_vocbase_t* _vocbase; aql::QueryResult _result; - size_t const _size; + arangodb::velocypack::ArrayIterator _iterator; bool _cached; }; diff --git a/lib/Basics/VelocyPackDumper.cpp b/lib/Basics/VelocyPackDumper.cpp index 0abff0ff67..c10f6655fb 100644 --- a/lib/Basics/VelocyPackDumper.cpp +++ b/lib/Basics/VelocyPackDumper.cpp @@ -25,12 +25,6 @@ #include "Basics/Exceptions.h" #include "Basics/fpconv.h" #include "Logger/Logger.h" -//#include "Basics/StringUtils.h" -//#include "Basics/Utf8Helper.h" -//#include "Basics/VPackStringBufferAdapter.h" -//#include "Basics/files.h" -//#include "Basics/hashes.h" -//#include "Basics/tri-strings.h" #include #include @@ -386,7 +380,9 @@ void VelocyPackDumper::dumpValue(VPackSlice const* slice, VPackSlice const* base throw VPackException(VPackException::NeedCustomTypeHandler); } else { std::string v = options->customTypeHandler->toString(*slice, nullptr, *base); + _buffer->appendChar('"'); dumpString(v.c_str(), v.size()); + _buffer->appendChar('"'); } break; }