1
0
Fork 0

ported all recent fixes from 1.3

This commit is contained in:
Jan Steemann 2013-05-16 21:04:04 +02:00
parent ac8e947fb6
commit ab6ca2f017
13 changed files with 578 additions and 98 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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

View File

@ -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*);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -963,6 +963,7 @@ Graph.prototype.removeEdge = function (edge, waitForSync) {
throw "cannot delete edge";
}
this._edgesCache[edge._properties._id] = undefined;
edge._properties = undefined;
}
};

View File

@ -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);

View File

@ -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