1
0
Fork 0

Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk

This commit is contained in:
Jan Steemann 2016-02-22 16:28:37 +01:00
commit 7efe1c6091
6 changed files with 161 additions and 10 deletions

View File

@ -220,6 +220,7 @@ add_executable(
Utils/Cursor.cpp
Utils/CursorRepository.cpp
Utils/DocumentHelper.cpp
Utils/OperationCursor.cpp
Utils/ShapedJsonTransformer.cpp
Utils/StandaloneTransactionContext.cpp
Utils/Transaction.cpp

View File

@ -0,0 +1,66 @@
////////////////////////////////////////////////////////////////////////////////
/// 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 Michael Hackstein
////////////////////////////////////////////////////////////////////////////////
#include "OperationCursor.h"
using namespace arangodb;
//////////////////////////////////////////////////////////////////////////////
/// @brief Get next default batchSize many elements.
/// Check hasMore()==true before using this
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
int OperationCursor::getMore() {
return getMore(_batchSize);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Get next batchSize many elements.
/// Check hasMore()==true before using this
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
int OperationCursor::getMore(uint64_t batchSize) {
// This may throw out of memory
if (!hasMore()) {
TRI_ASSERT(false);
// You requested more even if you should have checked it before.
return TRI_ERROR_FORBIDDEN;
}
// We restart the builder
_builder.clear();
VPackArrayBuilder guard(&_builder);
TRI_doc_mptr_t* mptr = nullptr;
// TODO: Improve this for baby awareness
while (batchSize > 0 && _limit > 0 && (mptr = _indexIterator->next()) != nullptr) {
--batchSize;
--_limit;
_builder.add(VPackSlice(mptr->vpack()));
}
if (batchSize > 0 || _limit == 0) {
// Iterator empty, there is no more
_hasMore = false;
}
return TRI_ERROR_NO_ERROR;
}

View File

@ -81,6 +81,10 @@ struct OperationCursor : public OperationResult {
~OperationCursor() {
}
IndexIterator* indexIterator() const {
return _indexIterator.get();
}
bool hasMore() const {
return _hasMore;

View File

@ -30,6 +30,7 @@
#include <velocypack/Builder.h>
#include <velocypack/Collection.h>
#include <velocypack/Options.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
@ -1362,6 +1363,10 @@ OperationResult Transaction::allLocal(std::string const& collectionName,
return OperationResult(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
if (orderDitch(trxCollection(cid)) == nullptr) {
return OperationResult(TRI_ERROR_OUT_OF_MEMORY);
}
int res = lock(trxCollection(cid), TRI_TRANSACTION_READ);
if (res != TRI_ERROR_NO_ERROR) {
@ -1433,8 +1438,63 @@ OperationResult Transaction::truncateCoordinator(std::string const& collectionNa
OperationResult Transaction::truncateLocal(std::string const& collectionName,
OperationOptions& options) {
// TODO
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
TRI_voc_cid_t cid = resolver()->getCollectionIdLocal(collectionName);
if (cid == 0) {
return OperationResult(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
if (orderDitch(trxCollection(cid)) == nullptr) {
return OperationResult(TRI_ERROR_OUT_OF_MEMORY);
}
int res = lock(trxCollection(cid), TRI_TRANSACTION_WRITE);
if (res != TRI_ERROR_NO_ERROR) {
return OperationResult(res);
}
TRI_document_collection_t* document = documentCollection(trxCollection(cid));
TRI_voc_rid_t actualRevision = 0;
TRI_doc_update_policy_t updatePolicy(TRI_DOC_UPDATE_LAST_WRITE, 0, &actualRevision);
VPackBuilder keyBuilder;
auto primaryIndex = document->primaryIndex();
std::function<void(TRI_doc_mptr_t*)> callback = [this, &document, &keyBuilder, &updatePolicy, &options](TRI_doc_mptr_t const* mptr) {
VPackSlice slice(mptr->vpack());
VPackSlice keySlice = slice.get(TRI_VOC_ATTRIBUTE_KEY);
keyBuilder.clear();
keyBuilder.openObject();
keyBuilder.add(TRI_VOC_ATTRIBUTE_KEY, keySlice);
keyBuilder.close();
VPackSlice builderSlice = keyBuilder.slice();
int res = document->remove(this, &builderSlice, &updatePolicy, options, false);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
};
try {
primaryIndex->invokeOnAllElements(callback);
}
catch (basics::Exception const& ex) {
unlock(trxCollection(cid), TRI_TRANSACTION_WRITE);
return OperationResult(ex.code());
}
res = unlock(trxCollection(cid), TRI_TRANSACTION_WRITE);
if (res != TRI_ERROR_NO_ERROR) {
return OperationCursor(res);
}
return OperationResult(TRI_ERROR_NO_ERROR);
}
////////////////////////////////////////////////////////////////////////////////
@ -1554,6 +1614,7 @@ OperationCursor Transaction::indexScan(
"Could not find primary index in collection '" + collectionName + "'.");
}
LOG(INFO) << "reverse: " << reverse;
iterator.reset(idx->allIterator(this, reverse));
break;
}

View File

@ -890,11 +890,11 @@ static void JS_AllQuery(v8::FunctionCallbackInfo<v8::Value> const& args) {
std::string collectionName(col->_name);
// We directly read the entire cursor. so batchsize == limit
OperationResult opRes = trx.indexScan(collectionName, Transaction::CursorType::ALL, "", {}, skip, limit, limit, false);
OperationCursor opCursor = trx.indexScan(collectionName, Transaction::CursorType::ALL, "", {}, skip, limit, limit, false);
if (opRes.failed()) {
trx.finish(opRes.code);
TRI_V8_THROW_EXCEPTION(opRes.code);
if (opCursor.failed()) {
trx.finish(opCursor.code);
TRI_V8_THROW_EXCEPTION(opCursor.code);
}
OperationResult countResult = trx.count(collectionName);
@ -912,9 +912,18 @@ static void JS_AllQuery(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_ASSERT(count.isNumber());
VPackOptions resultOptions = VPackOptions::Defaults;
resultOptions.customTypeHandler = opRes.customTypeHandler;
resultOptions.customTypeHandler = opCursor.customTypeHandler;
VPackSlice docs = opRes.slice();
if (!opCursor.hasMore()) {
// OUT OF MEMORY. initial hasMore should return true even if index is empty
TRI_V8_THROW_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
opCursor.getMore();
// We only need this one call, limit == batchsize
VPackSlice docs = opCursor.slice();
TRI_ASSERT(docs.isArray());
// setup result
v8::Handle<v8::Object> result = v8::Object::New(isolate);
auto documents = TRI_VPackToV8(isolate, docs, &resultOptions);

View File

@ -330,6 +330,10 @@ class AssocUnique {
}
public:
size_t buckets() const {
return _buckets.size();
}
//////////////////////////////////////////////////////////////////////////////
/// @brief checks if this index is empty
//////////////////////////////////////////////////////////////////////////////
@ -839,7 +843,8 @@ class AssocUnique {
}
//////////////////////////////////////////////////////////////////////////////
/// @brief a method to iterate over all elements in the hash
/// @brief a method to iterate over all elements in the hash. this method
/// can be used for deleting elements as well
//////////////////////////////////////////////////////////////////////////////
void invokeOnAllElements(CallbackElementFuncType callback) {
@ -847,11 +852,16 @@ class AssocUnique {
if (b._table == nullptr) {
continue;
}
for (size_t i = 0; i < b._nrAlloc; ++i) {
for (size_t i = 0; i < b._nrAlloc; /* no hoisting */) {
if (b._table[i] == nullptr) {
++i;
continue;
}
// don't increment i
callback(b._table[i]);
if (b._nrUsed == 0) {
break;
}
}
}
}