mirror of https://gitee.com/bigwinds/arangodb
ported all recent fixes from 1.3
This commit is contained in:
parent
ac8e947fb6
commit
ab6ca2f017
16
CHANGELOG
16
CHANGELOG
|
@ -12,7 +12,21 @@ v1.4
|
|||
* issue #512: Binded Parameters for LIMIT
|
||||
|
||||
|
||||
v1.3.0 (2013-05-XX)
|
||||
v1.3.1 (2013-XX-XX)
|
||||
-------------------
|
||||
|
||||
* set --javascript.app-path for test execution to prevent startup error
|
||||
|
||||
* issue #532: Graph _edgesCache returns invalid data?
|
||||
|
||||
* issue #531: Arangod errors
|
||||
|
||||
* issue #529: Really weird transaction issue
|
||||
|
||||
* fixed usage of --temp-path in aranogd and arangosh
|
||||
|
||||
|
||||
v1.3.0 (2013-05-10)
|
||||
-------------------
|
||||
|
||||
* fixed problem on restart ("datafile-xxx is not sealed") when server was killed
|
||||
|
|
|
@ -80,6 +80,7 @@ SERVER_OPT := \
|
|||
--database.force-sync-shapes false \
|
||||
--database.force-sync-properties false \
|
||||
--javascript.action-directory @top_srcdir@/js/actions \
|
||||
--javascript.app-path @top_srcdir@/js/apps \
|
||||
--javascript.gc-interval 1 \
|
||||
--javascript.modules-path @top_srcdir@/js/server/modules\;@top_srcdir@/js/common/modules\;@top_srcdir@/js/node \
|
||||
--javascript.package-path @top_srcdir@/js/npm\;@top_srcdir@/js/common/test-data/modules \
|
||||
|
|
|
@ -90,7 +90,6 @@ namespace triagens {
|
|||
T(),
|
||||
_setupState(TRI_ERROR_NO_ERROR),
|
||||
_nestingLevel(0),
|
||||
_readOnly(true),
|
||||
_hints(0),
|
||||
_timeout(0.0),
|
||||
_waitForSync(false),
|
||||
|
@ -141,6 +140,14 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the collection name resolver
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const CollectionNameResolver& resolver () const {
|
||||
return _resolver;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the transaction is embedded
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -150,11 +157,15 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether or not the transaction is read-only
|
||||
/// @brief whether or not shaped json in this trx should be copied
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool isReadOnlyTransaction () const {
|
||||
return _readOnly;
|
||||
inline bool mustCopyShapedJson () const {
|
||||
if (_trx != 0 && _trx->_hasOperations) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -312,10 +323,6 @@ namespace triagens {
|
|||
res = this->addCollectionToplevel(cid, type);
|
||||
}
|
||||
|
||||
if (type == TRI_TRANSACTION_WRITE) {
|
||||
_readOnly = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -992,12 +999,6 @@ namespace triagens {
|
|||
|
||||
int _nestingLevel;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the transaction is read-only
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool _readOnly;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction hints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -50,6 +50,31 @@ using namespace std;
|
|||
using namespace triagens::basics;
|
||||
using namespace triagens::arango;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private defines
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shortcut for read-only transaction class type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ReadTransactionType SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> >
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shortcut to wrap a shaped-json object in a read-only transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define WRAP_SHAPED_JSON(...) TRI_WrapShapedJson<ReadTransactionType>(__VA_ARGS__)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- HELPER FUNCTIONS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -985,7 +1010,7 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -1065,7 +1090,7 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, col, (TRI_doc_mptr_t const*) indexElement->_document, barrier);
|
||||
v8::Handle<v8::Value> doc = WRAP_SHAPED_JSON(trx, col->_cid, (TRI_doc_mptr_t const*) indexElement->_document, barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
@ -1175,7 +1200,7 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
|
@ -1267,13 +1292,14 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
if (total > skip && count < limit) {
|
||||
if (barrier == 0) {
|
||||
barrier = TRI_CreateBarrierElement(&primary->_barrierList);
|
||||
|
||||
if (barrier == 0) {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, col, data, barrier);
|
||||
v8::Handle<v8::Value> doc = WRAP_SHAPED_JSON(trx, col->_cid, data, barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
@ -1355,7 +1381,8 @@ static uint32_t SortGeoRandomGenerator (void) {
|
|||
/// @brief creates a geo result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int StoreGeoResult (TRI_vocbase_col_t const* collection,
|
||||
static int StoreGeoResult (ReadTransactionType& trx,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
GeoCoordinates* cors,
|
||||
v8::Handle<v8::Array>& documents,
|
||||
v8::Handle<v8::Array>& distances) {
|
||||
|
@ -1408,11 +1435,9 @@ static int StoreGeoResult (TRI_vocbase_col_t const* collection,
|
|||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
|
||||
// copy the documents
|
||||
for (gtr = tmp, i = 0; gtr < gnd; ++gtr, ++i) {
|
||||
documents->Set(i, TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) gtr->_data, barrier));
|
||||
documents->Set(i, WRAP_SHAPED_JSON(trx, collection->_cid, (TRI_doc_mptr_t const*) gtr->_data, barrier));
|
||||
distances->Set(i, v8::Number::New(gtr->_distance));
|
||||
}
|
||||
|
||||
|
@ -1457,7 +1482,7 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
|
@ -1538,7 +1563,7 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, col, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
v8::Handle<v8::Value> doc = WRAP_SHAPED_JSON(trx, col->_cid, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
// error
|
||||
|
@ -1596,7 +1621,7 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, col, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
v8::Handle<v8::Value> doc = WRAP_SHAPED_JSON(trx, col->_cid, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
@ -1666,7 +1691,7 @@ static v8::Handle<v8::Value> JS_AllQuery (v8::Arguments const& argv) {
|
|||
vector<TRI_doc_mptr_t> docs;
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
|
@ -1691,11 +1716,11 @@ static v8::Handle<v8::Value> JS_AllQuery (v8::Arguments const& argv) {
|
|||
// setup result
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
v8::Handle<v8::Array> documents = v8::Array::New(n);
|
||||
// reserver full capacity in one go
|
||||
// reserve full capacity in one go
|
||||
result->Set(v8::String::New("documents"), documents);
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
v8::Handle<v8::Value> document = TRI_WrapShapedJson(resolver, col, &docs[i], barrier);
|
||||
v8::Handle<v8::Value> document = WRAP_SHAPED_JSON(trx, col->_cid, &docs[i], barrier);
|
||||
|
||||
if (document.IsEmpty()) {
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
|
@ -1743,7 +1768,8 @@ static v8::Handle<v8::Value> JS_AnyQuery (v8::Arguments const& argv) {
|
|||
document._key = 0;
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -1768,7 +1794,7 @@ static v8::Handle<v8::Value> JS_AnyQuery (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::Null());
|
||||
}
|
||||
|
||||
return scope.Close(TRI_WrapShapedJson(resolver, col, &document, barrier));
|
||||
return scope.Close(WRAP_SHAPED_JSON(trx, col->_cid, &document, barrier));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1797,7 +1823,7 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
|
@ -1861,7 +1887,8 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
|
|||
else {
|
||||
for (size_t j = s; j < e; ++j) {
|
||||
TRI_doc_mptr_t* mptr = (TRI_doc_mptr_t*) TRI_AtVector(&filtered, j);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, col, mptr, barrier);
|
||||
|
||||
v8::Handle<v8::Value> doc = WRAP_SHAPED_JSON(trx, col->_cid, mptr, barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
@ -1903,7 +1930,7 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
|
|||
/// It is the callers responsibility to acquire and free the required locks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> ByExampleHashIndexQuery (TRI_document_collection_t* document,
|
||||
static v8::Handle<v8::Value> ByExampleHashIndexQuery (ReadTransactionType& trx,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
v8::Handle<v8::Object>* err,
|
||||
v8::Arguments const& argv) {
|
||||
|
@ -1934,8 +1961,7 @@ static v8::Handle<v8::Value> ByExampleHashIndexQuery (TRI_document_collection_t*
|
|||
result->Set(v8::String::New("documents"), documents);
|
||||
|
||||
// extract the index
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, collection, argv[0], false, err);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(trx.resolver(), collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
@ -1949,8 +1975,9 @@ static v8::Handle<v8::Value> ByExampleHashIndexQuery (TRI_document_collection_t*
|
|||
|
||||
// convert the example (index is locked by lockRead)
|
||||
TRI_index_search_value_t searchValue;
|
||||
|
||||
TRI_shaper_t* shaper = document->base._shaper;
|
||||
|
||||
TRI_primary_collection_t* primary = trx.primaryCollection();
|
||||
TRI_shaper_t* shaper = primary->_shaper;
|
||||
int res = SetupSearchValue(&hashIndex->_paths, example, shaper, searchValue, err);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -1973,13 +2000,13 @@ static v8::Handle<v8::Value> ByExampleHashIndexQuery (TRI_document_collection_t*
|
|||
CalculateSkipLimitSlice(total, skip, limit, s, e);
|
||||
|
||||
if (s < e) {
|
||||
TRI_barrier_t* barrier = TRI_CreateBarrierElement(&document->base._barrierList);
|
||||
TRI_barrier_t* barrier = TRI_CreateBarrierElement(&primary->_barrierList);
|
||||
if (barrier == 0) {
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
for (size_t i = s; i < e; ++i) {
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, collection, list._documents[i], barrier);
|
||||
v8::Handle<v8::Value> doc = WRAP_SHAPED_JSON(trx, collection->_cid, list._documents[i], barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
@ -2023,7 +2050,8 @@ static v8::Handle<v8::Value> JS_ByExampleHashIndex (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -2038,7 +2066,7 @@ static v8::Handle<v8::Value> JS_ByExampleHashIndex (v8::Arguments const& argv) {
|
|||
|
||||
trx.lockRead();
|
||||
|
||||
v8::Handle<v8::Value> result = ByExampleHashIndexQuery((TRI_document_collection_t*) trx.primaryCollection(), col, &err, argv);
|
||||
v8::Handle<v8::Value> result = ByExampleHashIndexQuery(trx, col, &err, argv);
|
||||
|
||||
trx.finish(res);
|
||||
|
||||
|
@ -2139,7 +2167,7 @@ static v8::Handle<v8::Value> JS_InEdgesQuery (v8::Arguments const& argv) {
|
|||
/// the caller must ensure all relevant locks are acquired and freed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> FulltextQuery (TRI_document_collection_t* document,
|
||||
static v8::Handle<v8::Value> FulltextQuery (ReadTransactionType& trx,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
v8::Handle<v8::Object>* err,
|
||||
v8::Arguments const& argv) {
|
||||
|
@ -2151,8 +2179,7 @@ static v8::Handle<v8::Value> FulltextQuery (TRI_document_collection_t* document,
|
|||
}
|
||||
|
||||
// extract the index
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, collection, argv[0], false, err);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(trx.resolver(), collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
@ -2206,7 +2233,7 @@ static v8::Handle<v8::Value> FulltextQuery (TRI_document_collection_t* document,
|
|||
result->Set(v8::String::New("documents"), documents);
|
||||
|
||||
for (uint32_t i = 0; i < queryResult->_numDocuments; ++i) {
|
||||
documents->Set(i, TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) queryResult->_documents[i], barrier));
|
||||
documents->Set(i, WRAP_SHAPED_JSON(trx, collection->_cid, (TRI_doc_mptr_t const*) queryResult->_documents[i], barrier));
|
||||
}
|
||||
|
||||
TRI_FreeResultFulltextIndex(queryResult);
|
||||
|
@ -2247,7 +2274,8 @@ static v8::Handle<v8::Value> JS_FulltextQuery (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -2262,7 +2290,7 @@ static v8::Handle<v8::Value> JS_FulltextQuery (v8::Arguments const& argv) {
|
|||
|
||||
trx.lockRead();
|
||||
|
||||
v8::Handle<v8::Value> result = FulltextQuery((TRI_document_collection_t*) trx.primaryCollection(), col, &err, argv);
|
||||
v8::Handle<v8::Value> result = FulltextQuery(trx, col, &err, argv);
|
||||
|
||||
trx.finish(res);
|
||||
|
||||
|
@ -2279,7 +2307,7 @@ static v8::Handle<v8::Value> JS_FulltextQuery (v8::Arguments const& argv) {
|
|||
/// the caller must ensure all relevant locks are acquired and freed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> NearQuery (TRI_document_collection_t* document,
|
||||
static v8::Handle<v8::Value> NearQuery (ReadTransactionType& trx,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
v8::Handle<v8::Object>* err,
|
||||
v8::Arguments const& argv) {
|
||||
|
@ -2291,8 +2319,7 @@ static v8::Handle<v8::Value> NearQuery (TRI_document_collection_t* document,
|
|||
}
|
||||
|
||||
// extract the index
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, collection, argv[0], false, err);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(trx.resolver(), collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
@ -2321,7 +2348,7 @@ static v8::Handle<v8::Value> NearQuery (TRI_document_collection_t* document,
|
|||
GeoCoordinates* cors = TRI_NearestGeoIndex(idx, latitude, longitude, limit);
|
||||
|
||||
if (cors != 0) {
|
||||
int res = StoreGeoResult(collection, cors, documents, distances);
|
||||
int res = StoreGeoResult(trx, collection, cors, documents, distances);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, res, "cannot add document to geo-index");
|
||||
|
@ -2346,7 +2373,8 @@ static v8::Handle<v8::Value> JS_NearQuery (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -2361,7 +2389,7 @@ static v8::Handle<v8::Value> JS_NearQuery (v8::Arguments const& argv) {
|
|||
|
||||
trx.lockRead();
|
||||
|
||||
v8::Handle<v8::Value> result = NearQuery((TRI_document_collection_t*) trx.primaryCollection(), col, &err, argv);
|
||||
v8::Handle<v8::Value> result = NearQuery(trx, col, &err, argv);
|
||||
|
||||
trx.finish(res);
|
||||
|
||||
|
@ -2413,7 +2441,7 @@ static v8::Handle<v8::Value> JS_TopQuery (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
|
@ -2442,10 +2470,15 @@ static v8::Handle<v8::Value> JS_TopQuery (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
TRI_barrier_t* barrier = TRI_CreateBarrierElement(&((TRI_primary_collection_t*) col->_collection)->_barrierList);
|
||||
v8::Handle<v8::Value> result = TRI_WrapShapedJson(resolver,
|
||||
col,
|
||||
(TRI_doc_mptr_t const*) elms->_elements[0]._document,
|
||||
barrier);
|
||||
|
||||
if (barrier == 0) {
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> result = WRAP_SHAPED_JSON(trx,
|
||||
col->_cid,
|
||||
(TRI_doc_mptr_t const*) elms->_elements[0]._document,
|
||||
barrier);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, elms->_elements);
|
||||
|
||||
|
@ -2459,7 +2492,7 @@ static v8::Handle<v8::Value> JS_TopQuery (v8::Arguments const& argv) {
|
|||
/// the caller must ensure all relevant locks are acquired and freed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> WithinQuery (TRI_document_collection_t* document,
|
||||
static v8::Handle<v8::Value> WithinQuery (ReadTransactionType& trx,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
v8::Handle<v8::Object>* err,
|
||||
v8::Arguments const& argv) {
|
||||
|
@ -2471,8 +2504,7 @@ static v8::Handle<v8::Value> WithinQuery (TRI_document_collection_t* document,
|
|||
}
|
||||
|
||||
// extract the index
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, collection, argv[0], false, err);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(trx.resolver(), collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
@ -2501,7 +2533,7 @@ static v8::Handle<v8::Value> WithinQuery (TRI_document_collection_t* document,
|
|||
GeoCoordinates* cors = TRI_WithinGeoIndex(idx, latitude, longitude, radius);
|
||||
|
||||
if (cors != 0) {
|
||||
int res = StoreGeoResult(collection, cors, documents, distances);
|
||||
int res = StoreGeoResult(trx, collection, cors, documents, distances);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, res, "cannot add document to geo-index");
|
||||
|
@ -2526,7 +2558,8 @@ static v8::Handle<v8::Value> JS_WithinQuery (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(col->_vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -2541,7 +2574,7 @@ static v8::Handle<v8::Value> JS_WithinQuery (v8::Arguments const& argv) {
|
|||
|
||||
trx.lockRead();
|
||||
|
||||
v8::Handle<v8::Value> result = WithinQuery((TRI_document_collection_t*) trx.primaryCollection(), col, &err, argv);
|
||||
v8::Handle<v8::Value> result = WithinQuery(trx, col, &err, argv);
|
||||
|
||||
trx.finish(res);
|
||||
|
||||
|
|
|
@ -89,6 +89,12 @@ static v8::Handle<v8::Value> WrapGeneralCursor (void* cursor);
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shortcut for read-only transaction class type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ReadTransactionType SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> >
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief macro to make sure we won't continue if we are inside a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -871,7 +877,8 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (const bool useCollection,
|
|||
assert(col);
|
||||
assert(key);
|
||||
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(vocbase, resolver, col->_cid);
|
||||
ReadTransactionType trx(vocbase, resolver, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -893,7 +900,8 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (const bool useCollection,
|
|||
res = trx.read(&document, key);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
result = TRI_WrapShapedJson(resolver, col, &document, barrier);
|
||||
result = TRI_WrapShapedJson<ReadTransactionType >(trx, col->_cid, &document, barrier);
|
||||
|
||||
if (! result.IsEmpty()) {
|
||||
freeBarrier = false;
|
||||
}
|
||||
|
@ -3438,7 +3446,8 @@ static v8::Handle<v8::Value> JS_CountVocbaseCol (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(collection->_vocbase, resolver, collection->_cid);
|
||||
ReadTransactionType trx(collection->_vocbase, resolver, collection->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -4515,7 +4524,8 @@ static v8::Handle<v8::Value> JS_FiguresVocbaseCol (v8::Arguments const& argv) {
|
|||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(collection->_vocbase, resolver, collection->_cid);
|
||||
ReadTransactionType trx(collection->_vocbase, resolver, collection->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -4603,7 +4613,8 @@ static v8::Handle<v8::Value> JS_GetIndexesVocbaseCol (v8::Arguments const& argv)
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(collection->_vocbase, resolver, collection->_cid);
|
||||
ReadTransactionType trx(collection->_vocbase, resolver, collection->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -5441,7 +5452,8 @@ static v8::Handle<v8::Value> JS_RevisionVocbaseCol (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(collection->_vocbase, resolver, collection->_cid);
|
||||
ReadTransactionType trx(collection->_vocbase, resolver, collection->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -6257,9 +6269,8 @@ static v8::Handle<v8::Value> JS_VersionVocbase (v8::Arguments const& argv) {
|
|||
static void WeakBarrierCallback (v8::Isolate* isolate,
|
||||
v8::Persistent<v8::Value> object,
|
||||
void* parameter) {
|
||||
TRI_barrier_t* barrier;
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) isolate->GetData();
|
||||
barrier = (TRI_barrier_t*) parameter;
|
||||
TRI_barrier_blocker_t* barrier = (TRI_barrier_blocker_t*) parameter;
|
||||
|
||||
LOG_TRACE("weak-callback for barrier called");
|
||||
|
||||
|
@ -6267,13 +6278,12 @@ static void WeakBarrierCallback (v8::Isolate* isolate,
|
|||
v8::Persistent<v8::Value> persistent = v8g->JSBarriers[barrier];
|
||||
v8g->JSBarriers.erase(barrier);
|
||||
|
||||
|
||||
// dispose and clear the persistent handle
|
||||
persistent.Dispose(isolate);
|
||||
persistent.Clear();
|
||||
|
||||
// free the barrier
|
||||
TRI_FreeBarrier(barrier);
|
||||
TRI_FreeBarrier(&barrier->base);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -6705,15 +6715,16 @@ v8::Handle<v8::Object> TRI_WrapCollection (TRI_vocbase_col_t const* collection)
|
|||
/// @brief wraps a TRI_shaped_json_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (const CollectionNameResolver& resolver,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
template<class T>
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (T& trx,
|
||||
TRI_voc_cid_t cid,
|
||||
TRI_doc_mptr_t const* document,
|
||||
TRI_barrier_t* barrier) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
TRI_ASSERT_MAINTAINER(document != 0);
|
||||
TRI_ASSERT_MAINTAINER(document->_key != 0);
|
||||
TRI_ASSERT_MAINTAINER(collection != 0);
|
||||
TRI_ASSERT_MAINTAINER(document->_data != 0);
|
||||
TRI_ASSERT_MAINTAINER(barrier != 0);
|
||||
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
|
@ -6728,9 +6739,39 @@ v8::Handle<v8::Value> TRI_WrapShapedJson (const CollectionNameResolver& resolver
|
|||
return scope.Close(result);
|
||||
}
|
||||
|
||||
TRI_barrier_blocker_t* blocker = (TRI_barrier_blocker_t*) barrier;
|
||||
bool doCopy = trx.mustCopyShapedJson();
|
||||
|
||||
if (doCopy) {
|
||||
// we'll create our own copy of the data
|
||||
TRI_df_marker_t const* m = static_cast<TRI_df_marker_t const*>(document->_data);
|
||||
|
||||
if (blocker->_data != NULL && blocker->_mustFree) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, blocker->_data);
|
||||
blocker->_data = NULL;
|
||||
blocker->_mustFree = false;
|
||||
}
|
||||
|
||||
blocker->_data = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, m->_size, false);
|
||||
|
||||
if (blocker->_data == 0) {
|
||||
// out of memory
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
memcpy(blocker->_data, m, m->_size);
|
||||
|
||||
blocker->_mustFree = true;
|
||||
}
|
||||
else {
|
||||
// we'll use the pointer into the datafile
|
||||
blocker->_data = const_cast<void*>(document->_data);
|
||||
}
|
||||
|
||||
|
||||
// point the 0 index Field to the c++ pointer for unwrapping later
|
||||
result->SetInternalField(SLOT_CLASS_TYPE, v8::Integer::New(WRP_SHAPED_JSON_TYPE));
|
||||
result->SetInternalField(SLOT_CLASS, v8::External::New(const_cast<void*>(document->_data)));
|
||||
result->SetInternalField(SLOT_CLASS, v8::External::New(blocker->_data));
|
||||
|
||||
map< void*, v8::Persistent<v8::Value> >::iterator i = v8g->JSBarriers.find(barrier);
|
||||
|
||||
|
@ -6748,7 +6789,7 @@ v8::Handle<v8::Value> TRI_WrapShapedJson (const CollectionNameResolver& resolver
|
|||
// store the document reference
|
||||
TRI_voc_rid_t rid = document->_rid;
|
||||
|
||||
result->Set(v8g->_IdKey, V8DocumentId(resolver.getCollectionName(collection->_cid), document->_key), v8::ReadOnly);
|
||||
result->Set(v8g->_IdKey, V8DocumentId(trx.resolver().getCollectionName(cid), document->_key), v8::ReadOnly);
|
||||
result->Set(v8g->_RevKey, V8RevisionId(rid), v8::ReadOnly);
|
||||
result->Set(v8g->_KeyKey, v8::String::New(document->_key), v8::ReadOnly);
|
||||
|
||||
|
@ -6757,8 +6798,8 @@ v8::Handle<v8::Value> TRI_WrapShapedJson (const CollectionNameResolver& resolver
|
|||
if (type == TRI_DOC_MARKER_KEY_EDGE) {
|
||||
TRI_doc_edge_key_marker_t* marker = (TRI_doc_edge_key_marker_t*) document->_data;
|
||||
|
||||
result->Set(v8g->_FromKey, V8DocumentId(resolver.getCollectionName(marker->_fromCid), ((char*) marker) + marker->_offsetFromKey));
|
||||
result->Set(v8g->_ToKey, V8DocumentId(resolver.getCollectionName(marker->_toCid), ((char*) marker) + marker->_offsetToKey));
|
||||
result->Set(v8g->_FromKey, V8DocumentId(trx.resolver().getCollectionName(marker->_fromCid), ((char*) marker) + marker->_offsetFromKey));
|
||||
result->Set(v8g->_ToKey, V8DocumentId(trx.resolver().getCollectionName(marker->_toCid), ((char*) marker) + marker->_offsetToKey));
|
||||
}
|
||||
|
||||
// and return
|
||||
|
|
|
@ -78,8 +78,9 @@ v8::Handle<v8::Object> TRI_WrapCollection (TRI_vocbase_col_t const*);
|
|||
/// @brief wraps a TRI_shaped_json_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (const triagens::arango::CollectionNameResolver&,
|
||||
TRI_vocbase_col_t const*,
|
||||
template<class T>
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (T&,
|
||||
TRI_voc_cid_t,
|
||||
TRI_doc_mptr_t const*,
|
||||
TRI_barrier_t*);
|
||||
|
||||
|
|
|
@ -43,6 +43,22 @@
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free data associated with a barrier
|
||||
/// currently only barriers pointing to shaped json might contain data that
|
||||
/// needs to be freed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FreeDataBarrier (TRI_barrier_t* element) {
|
||||
if (element->_type == TRI_BARRIER_ELEMENT) {
|
||||
TRI_barrier_blocker_t* b = (TRI_barrier_blocker_t*) element;
|
||||
|
||||
if (b->_data != NULL && b->_mustFree) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, b->_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief inserts the barrier element into the linked list of barrier elemnents
|
||||
/// of the collection
|
||||
|
@ -121,6 +137,8 @@ void TRI_DestroyBarrierList (TRI_barrier_list_t* container) {
|
|||
ptr->_type == TRI_BARRIER_COLLECTION_COMPACTION) {
|
||||
|
||||
// free data still allocated in barrier elements
|
||||
FreeDataBarrier(ptr);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, ptr);
|
||||
}
|
||||
else if (ptr->_type == TRI_BARRIER_ELEMENT) {
|
||||
|
@ -150,6 +168,7 @@ bool TRI_ContainsBarrierList (TRI_barrier_list_t* container, TRI_barrier_type_e
|
|||
while (ptr != NULL) {
|
||||
if (ptr->_type == type) {
|
||||
TRI_UnlockSpin(&container->_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
ptr = ptr->_next;
|
||||
|
@ -176,6 +195,8 @@ TRI_barrier_t* TRI_CreateBarrierElementZ (TRI_barrier_list_t* container,
|
|||
}
|
||||
|
||||
element->base._type = TRI_BARRIER_ELEMENT;
|
||||
element->_data = NULL;
|
||||
element->_mustFree = false;
|
||||
|
||||
element->_line = line;
|
||||
element->_filename = filename;
|
||||
|
@ -350,6 +371,10 @@ void TRI_FreeBarrier (TRI_barrier_t* element) {
|
|||
}
|
||||
|
||||
TRI_UnlockSpin(&container->_lock);
|
||||
|
||||
// free data contained in the element
|
||||
// currently, only barriers of type ELEMENT contain data that needs freeing
|
||||
FreeDataBarrier(element);
|
||||
|
||||
// free the element
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, element);
|
||||
|
|
|
@ -86,6 +86,8 @@ TRI_barrier_t;
|
|||
typedef struct TRI_barrier_blocker_s {
|
||||
TRI_barrier_t base;
|
||||
|
||||
void* _data;
|
||||
bool _mustFree;
|
||||
size_t _line;
|
||||
char const* _filename;
|
||||
}
|
||||
|
|
|
@ -758,6 +758,9 @@ static int RollbackUpdate (TRI_document_collection_t* document,
|
|||
|
||||
// ignore any errors we're getting from this
|
||||
DeleteSecondaryIndexes(document, newHeader, true);
|
||||
|
||||
// put back the header into its old position
|
||||
document->_headers->move(document->_headers, newHeader, oldHeader);
|
||||
|
||||
*newHeader = *oldHeader;
|
||||
|
||||
|
@ -767,9 +770,6 @@ static int RollbackUpdate (TRI_document_collection_t* document,
|
|||
LOG_ERROR("error rolling back update operation");
|
||||
}
|
||||
|
||||
// put back the header into its old position
|
||||
document->_headers->move(document->_headers, newHeader, newHeader);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,8 @@ static void MoveBackHeader (TRI_headers_t* h,
|
|||
// we have at least one element in the list
|
||||
TRI_ASSERT_MAINTAINER(headers->_begin != NULL);
|
||||
TRI_ASSERT_MAINTAINER(headers->_end != NULL);
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
TRI_ASSERT_MAINTAINER(header->_next != header);
|
||||
|
||||
if (headers->_end == header) {
|
||||
// header is already at the end
|
||||
|
@ -157,6 +159,8 @@ static void MoveBackHeader (TRI_headers_t* h,
|
|||
|
||||
TRI_ASSERT_MAINTAINER(headers->_begin != NULL);
|
||||
TRI_ASSERT_MAINTAINER(headers->_end != NULL);
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
TRI_ASSERT_MAINTAINER(header->_next != header);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -167,6 +171,12 @@ static void UnlinkHeader (TRI_headers_t* h,
|
|||
TRI_doc_mptr_t* header) {
|
||||
simple_headers_t* headers = (simple_headers_t*) h;
|
||||
|
||||
//printf("UNLINK\n-------------\n");
|
||||
//h->dump(h);
|
||||
TRI_ASSERT_MAINTAINER(header != NULL);
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
TRI_ASSERT_MAINTAINER(header->_next != header);
|
||||
|
||||
// unlink the header
|
||||
if (header->_prev != NULL) {
|
||||
header->_prev->_next = header->_next;
|
||||
|
@ -199,10 +209,13 @@ static void UnlinkHeader (TRI_headers_t* h,
|
|||
TRI_ASSERT_MAINTAINER(headers->_begin != NULL);
|
||||
TRI_ASSERT_MAINTAINER(headers->_end != NULL);
|
||||
}
|
||||
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
TRI_ASSERT_MAINTAINER(header->_next != header);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief moves a header back into the list, using its previous position
|
||||
/// @brief moves a header around in the list, using its previous position
|
||||
/// (specified in "old")
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -216,26 +229,61 @@ static void MoveHeader (TRI_headers_t* h,
|
|||
}
|
||||
|
||||
TRI_ASSERT_MAINTAINER(headers->_nrAllocated > 0);
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
TRI_ASSERT_MAINTAINER(header->_next != header);
|
||||
|
||||
// adjust list start and end pointers
|
||||
if (old->_prev == NULL) {
|
||||
headers->_begin = header;
|
||||
}
|
||||
if (old->_next == NULL) {
|
||||
headers->_end = header;
|
||||
}
|
||||
if (header->_prev != NULL && header->_prev == old->_next) {
|
||||
header->_prev->_next = NULL;
|
||||
headers->_end = header->_prev;
|
||||
}
|
||||
else if (header->_next != NULL && header->_next == old->_prev) {
|
||||
header->_next->_prev = NULL;
|
||||
headers->_begin = header->_next;
|
||||
}
|
||||
/*
|
||||
if (headers->_begin == old->_next) {
|
||||
// adjust list start pointer
|
||||
headers->_begin = header;
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
if (old->_next == NULL) {
|
||||
// adjust list end pointer
|
||||
headers->_end = header;
|
||||
}
|
||||
*/
|
||||
|
||||
if (old->_prev != NULL) {
|
||||
old->_prev->_next = header;
|
||||
header->_prev = old->_prev;
|
||||
}
|
||||
else {
|
||||
header->_prev = NULL;
|
||||
}
|
||||
|
||||
if (old->_next != NULL) {
|
||||
old->_next->_prev = header;
|
||||
header->_next = old->_next;
|
||||
}
|
||||
|
||||
else {
|
||||
header->_next = NULL;
|
||||
}
|
||||
/*
|
||||
header->_prev = old->_prev;
|
||||
header->_next = old->_next;
|
||||
*/
|
||||
|
||||
TRI_ASSERT_MAINTAINER(headers->_begin != NULL);
|
||||
TRI_ASSERT_MAINTAINER(headers->_end != NULL);
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
TRI_ASSERT_MAINTAINER(header->_next != header);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -257,6 +305,9 @@ static void RelinkHeader (TRI_headers_t* h,
|
|||
|
||||
MoveHeader(h, header, old);
|
||||
headers->_nrLinked++;
|
||||
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
TRI_ASSERT_MAINTAINER(header->_next != header);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -402,13 +453,13 @@ static void DumpHeaders (TRI_headers_t const* h) {
|
|||
TRI_doc_mptr_t* next = headers->_begin;
|
||||
size_t i = 0;
|
||||
|
||||
LOG_TRACE("number of allocated headers: %lu\n", (unsigned long) headers->_nrAllocated);
|
||||
LOG_TRACE("number of linked headers: %lu\n", (unsigned long) headers->_nrLinked);
|
||||
LOG_TRACE("begin ptr: %p\n", headers->_begin);
|
||||
LOG_TRACE("end ptr: %p\n", headers->_end);
|
||||
printf("number of allocated headers: %lu\n", (unsigned long) headers->_nrAllocated);
|
||||
printf("number of linked headers: %lu\n", (unsigned long) headers->_nrLinked);
|
||||
printf("begin ptr: %p\n", headers->_begin);
|
||||
printf("end ptr: %p\n", headers->_end);
|
||||
|
||||
while (next != NULL) {
|
||||
LOG_TRACE("- header #%lu: ptr: %p, prev: %p, next: %p, key: %s\n",
|
||||
printf("- header #%lu: ptr: %p, prev: %p, next: %p, key: %s\n",
|
||||
(unsigned long) i,
|
||||
next,
|
||||
next->_prev,
|
||||
|
@ -424,7 +475,6 @@ static void DumpHeaders (TRI_headers_t const* h) {
|
|||
}
|
||||
|
||||
TRI_ASSERT_MAINTAINER(i == headers->_nrLinked);
|
||||
TRI_ASSERT_MAINTAINER(i == headers->_nrLinked);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -963,6 +963,7 @@ Graph.prototype.removeEdge = function (edge, waitForSync) {
|
|||
throw "cannot delete edge";
|
||||
}
|
||||
|
||||
this._edgesCache[edge._properties._id] = undefined;
|
||||
edge._properties = undefined;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1439,6 +1439,314 @@ function transactionOperationsSuite () {
|
|||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function transactionBarriersSuite () {
|
||||
var cn1 = "UnitTestsTransaction1";
|
||||
var cn2 = "UnitTestsTransaction2";
|
||||
|
||||
var c1 = null;
|
||||
var c2 = null;
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
db._drop(cn1);
|
||||
db._drop(cn2);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
if (c1 !== null) {
|
||||
c1.drop();
|
||||
}
|
||||
|
||||
c1 = null;
|
||||
|
||||
if (c2 !== null) {
|
||||
c2.drop();
|
||||
}
|
||||
|
||||
c2 = null;
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: usage of barriers outside of transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testBarriersOutsideCommit : function () {
|
||||
c1 = db._create(cn1);
|
||||
|
||||
var docs = [ ];
|
||||
var i;
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn1 ]
|
||||
},
|
||||
action : function () {
|
||||
for (i = 0; i < 100; ++i) {
|
||||
c1.save({ _key: "foo" + i, value1: i, value2: "foo" + i + "x" });
|
||||
}
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
docs.push(c1.document("foo" + i));
|
||||
}
|
||||
|
||||
return c1.document("foo0");
|
||||
}
|
||||
};
|
||||
|
||||
var result = TRANSACTION(obj);
|
||||
|
||||
assertEqual(100, docs.length);
|
||||
assertEqual(100, c1.count());
|
||||
|
||||
assertEqual("foo0", result._key);
|
||||
assertEqual(0, result.value1);
|
||||
assertEqual("foo0x", result.value2);
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
assertEqual("foo" + i, docs[i]._key);
|
||||
assertEqual(i, docs[i].value1);
|
||||
assertEqual("foo" + i + "x", docs[i].value2);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: usage of barriers outside of transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testBarriersOutsideRollback : function () {
|
||||
c1 = db._create(cn1);
|
||||
|
||||
var docs = [ ];
|
||||
var i;
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn1 ]
|
||||
},
|
||||
action : function () {
|
||||
for (i = 0; i < 100; ++i) {
|
||||
c1.save({ _key: "foo" + i, value1: i, value2: "foo" + i + "x" });
|
||||
}
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
docs.push(c1.document("foo" + i));
|
||||
}
|
||||
|
||||
throw "doh!";
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
assertEqual(100, docs.length);
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
assertEqual("foo" + i, docs[i]._key);
|
||||
assertEqual(i, docs[i].value1);
|
||||
assertEqual("foo" + i + "x", docs[i].value2);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- test suite
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function transactionGraphSuite () {
|
||||
var cn1 = "UnitTestsVertices";
|
||||
var cn2 = "UnitTestsEdges";
|
||||
|
||||
var g = require('org/arangodb/graph').Graph;
|
||||
|
||||
var c1 = null;
|
||||
var c2 = null;
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
db._drop(cn1);
|
||||
db._drop(cn2);
|
||||
|
||||
db._create(cn1);
|
||||
db._createEdgeCollection(cn2);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
if (c1 !== null) {
|
||||
c1.drop();
|
||||
}
|
||||
|
||||
c1 = null;
|
||||
|
||||
if (c2 !== null) {
|
||||
c2.drop();
|
||||
}
|
||||
|
||||
c2 = null;
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback updates in a graph transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackGraphUpdates : function () {
|
||||
var graph;
|
||||
|
||||
try {
|
||||
graph = new g('UnitTestsGraph');
|
||||
graph.drop();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
graph = new g('UnitTestsGraph', cn1, cn2);
|
||||
var gotHere = 0;
|
||||
|
||||
var obj = {
|
||||
collections: {
|
||||
write: [ cn1, cn2 ]
|
||||
},
|
||||
action : function () {
|
||||
var result = { };
|
||||
result.enxirvp = graph.addVertex(null, { _rev : null })._properties;
|
||||
result.biitqtk = graph.addVertex(null, { _rev : null })._properties;
|
||||
result.oboyuhh = graph.addEdge(graph.getVertex(result.enxirvp._id), graph.getVertex(result.biitqtk._id), null, { name: "john smith" })._properties;
|
||||
result.cvwmkym = db[cn1].replace(result.enxirvp._id, { _rev : null });
|
||||
result.gsalfxu = db[cn1].replace(result.biitqtk._id, { _rev : null });
|
||||
result.xsjzbst = function (){
|
||||
graph.removeEdge(graph.getEdge(result.oboyuhh._id));
|
||||
return true;
|
||||
}();
|
||||
|
||||
result.thizhdd = graph.addEdge(graph.getVertex(result.cvwmkym._id), graph.getVertex(result.gsalfxu._id), result.oboyuhh._key, { name: "david smith" });
|
||||
gotHere = 1;
|
||||
|
||||
result.rldfnre = graph.addEdge(graph.getVertex(result.cvwmkym._id), graph.getVertex(result.gsalfxu._id), result.oboyuhh._key, { name : "david smith" })._properties;
|
||||
gotHere = 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
assertEqual(0, db[cn1].count());
|
||||
assertEqual(0, db[cn2].count());
|
||||
assertEqual(1, gotHere);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: usage of barriers outside of graph transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testUseBarriersOutsideGraphTransaction : function () {
|
||||
var graph;
|
||||
|
||||
try {
|
||||
graph = new g('UnitTestsGraph');
|
||||
graph.drop();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
graph = new g('UnitTestsGraph', cn1, cn2);
|
||||
|
||||
var obj = {
|
||||
collections: {
|
||||
write: [ cn1, cn2 ]
|
||||
},
|
||||
action : function () {
|
||||
var result = { };
|
||||
|
||||
result.enxirvp = graph.addVertex(null, { _rev : null })._properties;
|
||||
result.biitqtk = graph.addVertex(null, { _rev : null })._properties;
|
||||
result.oboyuhh = graph.addEdge(graph.getVertex(result.enxirvp._id), graph.getVertex(result.biitqtk._id), null, { name : "john smith" })._properties;
|
||||
result.cvwmkym = db[cn1].replace(result.enxirvp._id, { _rev : null });
|
||||
result.gsalfxu = db[cn1].replace(result.biitqtk._id, { _rev : null });
|
||||
result.xsjzbst = function (){
|
||||
graph.removeEdge(graph.getEdge(result.oboyuhh._id));
|
||||
return true;
|
||||
}();
|
||||
|
||||
result.rldfnre = graph.addEdge(graph.getVertex(result.cvwmkym._id), graph.getVertex(result.gsalfxu._id), result.oboyuhh._key, { name : "david smith" })._properties;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
var result = TRANSACTION(obj);
|
||||
assertTrue(result.enxirvp._key.length > 0);
|
||||
assertEqual(undefined, result.enxirvp.name);
|
||||
|
||||
assertTrue(result.biitqtk._key.length > 0);
|
||||
assertEqual(undefined, result.biitqtk.name);
|
||||
|
||||
assertTrue(result.oboyuhh._key.length > 0);
|
||||
assertEqual("john smith", result.oboyuhh.name);
|
||||
assertEqual(null, result.oboyuhh.$label);
|
||||
assertTrue(result.oboyuhh._from.length > 0);
|
||||
assertTrue(result.oboyuhh._to.length > 0);
|
||||
|
||||
assertTrue(result.cvwmkym._key.length > 0);
|
||||
assertEqual(undefined, result.cvwmkym.name);
|
||||
assertEqual(result.enxirvp._rev, result.cvwmkym._oldRev);
|
||||
|
||||
assertTrue(result.gsalfxu._key.length > 0);
|
||||
assertEqual(undefined, result.gsalfxu.name);
|
||||
assertEqual(result.biitqtk._rev, result.gsalfxu._oldRev);
|
||||
|
||||
assertEqual(true, result.xsjzbst);
|
||||
|
||||
assertTrue(result.rldfnre._key.length > 0);
|
||||
assertEqual(result.oboyuhh._key, result.rldfnre._key);
|
||||
assertEqual("david smith", result.rldfnre.name);
|
||||
assertEqual(null, result.rldfnre.$label);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- test suite
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function transactionRollbackSuite () {
|
||||
var cn1 = "UnitTestsTransaction1";
|
||||
|
||||
|
@ -2130,7 +2438,7 @@ function transactionRollbackSuite () {
|
|||
c1.save({ _key: "test" });
|
||||
assertEqual(3, c1.count());
|
||||
assertEqual([ "bar", "baz", "test" ], sortedKeys(c1));
|
||||
},
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -2601,6 +2909,8 @@ function transactionCrossCollectionSuite () {
|
|||
jsunity.run(transactionInvocationSuite);
|
||||
jsunity.run(transactionCollectionsSuite);
|
||||
jsunity.run(transactionOperationsSuite);
|
||||
jsunity.run(transactionBarriersSuite);
|
||||
jsunity.run(transactionGraphSuite);
|
||||
jsunity.run(transactionRollbackSuite);
|
||||
jsunity.run(transactionCountSuite);
|
||||
jsunity.run(transactionCrossCollectionSuite);
|
||||
|
|
|
@ -240,7 +240,8 @@
|
|||
|
||||
// create the _routing collection
|
||||
addTask("createRouting", "setup _routing collection", function () {
|
||||
return createSystemCollection("_routing");
|
||||
// needs to be big enough for assets
|
||||
return createSystemCollection("_routing", { journalSize: 32 * 1024 * 1024 });
|
||||
});
|
||||
|
||||
// create the default route in the _routing collection
|
||||
|
|
Loading…
Reference in New Issue