1
0
Fork 0

documents and edges are now created using transaction contexts

This commit is contained in:
Jan Steemann 2012-11-16 15:36:44 +01:00
parent c2689f0f5e
commit 38025fbc31
5 changed files with 173 additions and 258 deletions

View File

@ -32,6 +32,7 @@
#include "Utils/CollectionWriteLock.h" #include "Utils/CollectionWriteLock.h"
#include "ShapedJson/shaped-json.h"
#include "VocBase/transaction.h" #include "VocBase/transaction.h"
#include "VocBase/vocbase.h" #include "VocBase/vocbase.h"
@ -113,7 +114,7 @@ namespace triagens {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create a single document within a transaction /// @brief create a single document within a transaction, using json
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int createDocument (TRI_doc_mptr_t** mptr, int createDocument (TRI_doc_mptr_t** mptr,
@ -130,7 +131,7 @@ namespace triagens {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create a single edge within a transaction /// @brief create a single edge within a transaction, using json
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int createEdge (TRI_doc_mptr_t** mptr, int createEdge (TRI_doc_mptr_t** mptr,
@ -147,6 +148,43 @@ namespace triagens {
return this->createCollectionDocument(primary, TRI_DOC_MARKER_KEY_EDGE, mptr, json, data, forceSync); return this->createCollectionDocument(primary, TRI_DOC_MARKER_KEY_EDGE, mptr, json, data, forceSync);
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief create a single edge within a transaction, using shaped json
////////////////////////////////////////////////////////////////////////////////
int createDocument (TRI_voc_key_t key,
TRI_doc_mptr_t** mptr,
TRI_shaped_json_t const* shaped,
bool forceSync) {
if (_numWrites++ > N) {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
TRI_primary_collection_t* primary = this->primaryCollection();
_synchronous = forceSync || primary->base._info._waitForSync;
return this->createCollectionShaped(primary, TRI_DOC_MARKER_KEY_DOCUMENT, key, mptr, shaped, 0, forceSync);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a single edge within a transaction, using shaped json
////////////////////////////////////////////////////////////////////////////////
int createEdge (TRI_voc_key_t key,
TRI_doc_mptr_t** mptr,
TRI_shaped_json_t const* shaped,
bool forceSync,
void const* data) {
if (_numWrites++ > N) {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
TRI_primary_collection_t* primary = this->primaryCollection();
_synchronous = forceSync || primary->base._info._waitForSync;
return this->createCollectionShaped(primary, TRI_DOC_MARKER_KEY_EDGE, key, mptr, shaped, data, forceSync);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief update a single document within a transaction /// @brief update a single document within a transaction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -243,6 +243,14 @@ namespace triagens {
return this->_trxName; return this->_trxName;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief get the "vocbase"
////////////////////////////////////////////////////////////////////////////////
inline TRI_vocbase_t* vocbase () const {
return this->_vocbase;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get the status of the transaction /// @brief get the status of the transaction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -333,7 +341,7 @@ namespace triagens {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create a single document /// @brief create a single document, using JSON
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int createCollectionDocument (TRI_primary_collection_t* const primary, int createCollectionDocument (TRI_primary_collection_t* const primary,
@ -351,7 +359,26 @@ namespace triagens {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief update a single document /// @brief create a single document, using shaped json
////////////////////////////////////////////////////////////////////////////////
int createCollectionShaped (TRI_primary_collection_t* const primary,
const TRI_df_marker_type_e markerType,
TRI_voc_key_t key,
TRI_doc_mptr_t** mptr,
TRI_shaped_json_t const* shaped,
void const* data,
const bool forceSync) {
TRI_doc_operation_context_t context;
TRI_InitContextPrimaryCollection(&context, primary, TRI_DOC_UPDATE_ERROR, forceSync);
CollectionWriteLock lock(primary);
return primary->create(&context, markerType, mptr, shaped, data, key);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief update a single document, using JSON
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int updateCollectionDocument (TRI_primary_collection_t* const primary, int updateCollectionDocument (TRI_primary_collection_t* const primary,

View File

@ -555,17 +555,17 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (TRI_vocbase_t* vocbase,
"usage: document(<document-handle>)"))); "usage: document(<document-handle>)")));
} }
ResourceHolder holder;
TRI_voc_key_t key = 0; TRI_voc_key_t key = 0;
TRI_voc_rid_t rid; TRI_voc_rid_t rid;
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, lock, argv[0]); v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, lock, argv[0]);
holder.registerString(TRI_CORE_MEM_ZONE, key);
if (! err.IsEmpty()) { if (! err.IsEmpty()) {
if (collection != 0 && lock) { if (collection != 0 && lock) {
TRI_ReleaseCollection(collection); TRI_ReleaseCollection(collection);
} }
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
return scope.Close(v8::ThrowException(err)); return scope.Close(v8::ThrowException(err));
} }
@ -589,7 +589,6 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (TRI_vocbase_t* vocbase,
} }
int res = primary->read(&readContext, &document, key); int res = primary->read(&readContext, &document, key);
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
if (res == TRI_ERROR_NO_ERROR) { if (res == TRI_ERROR_NO_ERROR) {
TRI_barrier_t* barrier; TRI_barrier_t* barrier;
@ -637,17 +636,18 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (TRI_vocbase_t* vocbase,
"usage: replace(<document>, <data>, <overwrite>, <waitForSync>)"))); "usage: replace(<document>, <data>, <overwrite>, <waitForSync>)")));
} }
ResourceHolder holder;
TRI_voc_key_t key = 0; TRI_voc_key_t key = 0;
TRI_voc_rid_t rid; TRI_voc_rid_t rid;
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, true, argv[0]); v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, true, argv[0]);
holder.registerString(TRI_CORE_MEM_ZONE, key);
if (! err.IsEmpty()) { if (! err.IsEmpty()) {
if (collection != 0) { if (collection != 0) {
TRI_ReleaseCollection(collection); TRI_ReleaseCollection(collection);
} }
if (key) TRI_FreeString(TRI_CORE_MEM_ZONE, key);
return scope.Close(v8::ThrowException(err)); return scope.Close(v8::ThrowException(err));
} }
@ -657,7 +657,6 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (TRI_vocbase_t* vocbase,
if (shaped == 0) { if (shaped == 0) {
TRI_ReleaseCollection(collection); TRI_ReleaseCollection(collection);
if (key) TRI_FreeString(TRI_CORE_MEM_ZONE, key);
return scope.Close(v8::ThrowException( return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_errno(), TRI_CreateErrorObject(TRI_errno(),
"<data> cannot be converted into JSON shape"))); "<data> cannot be converted into JSON shape")));
@ -699,9 +698,6 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (TRI_vocbase_t* vocbase,
TRI_doc_mptr_t* document = 0; TRI_doc_mptr_t* document = 0;
int res = primary->update(&context, &document, shaped, key); int res = primary->update(&context, &document, shaped, key);
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
// ............................................................................. // .............................................................................
// outside a write transaction // outside a write transaction
@ -761,10 +757,10 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (TRI_vocbase_t* vocbase,
/// @verbinclude shell_create-document /// @verbinclude shell_create-document
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_TRX
static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1>* trx, static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1>* trx,
v8::Arguments const& argv) { v8::Arguments const& argv) {
v8::HandleScope scope; v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
if (argv.Length() < 1 || argv.Length() > 2) { if (argv.Length() < 1 || argv.Length() > 2) {
return scope.Close(v8::ThrowException( return scope.Close(v8::ThrowException(
@ -772,16 +768,32 @@ static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<Em
"usage: save(<data>, <waitForSync>)"))); "usage: save(<data>, <waitForSync>)")));
} }
TRI_json_t* json = TRI_JsonObject(argv[0]); ResourceHolder holder;
bool forceSync = false; // set document key
if (2 == argv.Length()) { TRI_voc_key_t key = 0;
forceSync = TRI_ObjectToBoolean(argv[1]);
if (argv[0]->IsObject()) {
v8::Handle<v8::Object> obj = argv[0]->ToObject();
v8::Handle<v8::Value> v = obj->Get(v8g->KeyKey);
if (v->IsString()) {
TRI_Utf8ValueNFC str(TRI_CORE_MEM_ZONE, v);
key = TRI_DuplicateString2(*str, str.length());
holder.registerString(TRI_CORE_MEM_ZONE, key);
}
} }
// the lock is freed in create TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[0], trx->shaper());
if (! holder.registerShapedJson(trx->shaper(), shaped)) {
return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_errno(),
"<data> cannot be converted into JSON shape")));
}
const bool forceSync = (argv.Length() == 2 && TRI_ObjectToBoolean(argv[1]));
TRI_doc_mptr_t* document = 0; TRI_doc_mptr_t* document = 0;
int res = trx->createDocument(&document, json, forceSync); int res = trx->createDocument(key, &document, shaped, forceSync);
res = trx->finish(res); res = trx->finish(res);
@ -792,10 +804,6 @@ static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<Em
assert(document); assert(document);
assert(document->_key); assert(document->_key);
TRI_v8_global_t* v8g;
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
string id = StringUtils::itoa(trx->cid()) + string(TRI_DOCUMENT_HANDLE_SEPARATOR_STR) + string(document->_key); string id = StringUtils::itoa(trx->cid()) + string(TRI_DOCUMENT_HANDLE_SEPARATOR_STR) + string(document->_key);
v8::Handle<v8::Object> result = v8::Object::New(); v8::Handle<v8::Object> result = v8::Object::New();
@ -805,92 +813,6 @@ static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<Em
return scope.Close(result); return scope.Close(result);
} }
#else
static v8::Handle<v8::Value> SaveVocbaseCol (TRI_vocbase_col_t const* collection,
v8::Arguments const& argv) {
v8::HandleScope scope;
TRI_v8_global_t* v8g;
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_primary_collection_t* primary = collection->_collection;
if (argv.Length() < 1 || argv.Length() > 2) {
return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_ERROR_BAD_PARAMETER,
"usage: save(<data>, <waitForSync>)")));
}
// set document key
TRI_voc_key_t key = 0;
if (argv[0]->IsObject()) {
v8::Handle<v8::Value> v = argv[0]->ToObject()->Get(v8g->KeyKey);
if (v->IsString()) {
TRI_Utf8ValueNFC str(TRI_CORE_MEM_ZONE, v);
key = TRI_DuplicateString2(*str, str.length());
}
}
bool forceSync = false;
if (2 == argv.Length()) {
forceSync = TRI_ObjectToBoolean(argv[1]);
}
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[0], primary->_shaper);
if (shaped == 0) {
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_errno(),
"<data> cannot be converted into JSON shape")));
}
// .............................................................................
// inside a write transaction
// .............................................................................
TRI_doc_operation_context_t context;
TRI_InitContextPrimaryCollection(&context, primary, TRI_DOC_UPDATE_ERROR, forceSync);
context._release = true;
primary->beginWrite(primary);
// the lock is freed in create
TRI_doc_mptr_t* document = 0;
int res = primary->create(&context, TRI_DOC_MARKER_KEY_DOCUMENT, &document, shaped, 0, key);
if (key) {
TRI_Free(TRI_CORE_MEM_ZONE, key);
}
// .............................................................................
// outside a write transaction
// .............................................................................
TRI_FreeShapedJson(primary->_shaper, shaped);
if (res != TRI_ERROR_NO_ERROR) {
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot save document", true)));
}
assert(document);
assert(document->_key);
string id = StringUtils::itoa(collection->_cid) + string(TRI_DOCUMENT_HANDLE_SEPARATOR_STR) + string(document->_key);
v8::Handle<v8::Object> result = v8::Object::New();
result->Set(v8g->DidKey, v8::String::New(id.c_str()));
result->Set(v8g->RevKey, v8::Number::New(document->_rid));
result->Set(v8g->KeyKey, v8::String::New(document->_key));
return scope.Close(result);
}
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief saves a new edge document /// @brief saves a new edge document
@ -918,14 +840,10 @@ static v8::Handle<v8::Value> SaveVocbaseCol (TRI_vocbase_col_t const* collection
/// @TINYEXAMPLE{shell_create-edge,create an edge} /// @TINYEXAMPLE{shell_create-edge,create an edge}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> SaveEdgeCol (TRI_vocbase_col_t const* collection, static v8::Handle<v8::Value> SaveEdgeCol (SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1>* trx,
v8::Arguments const& argv) { v8::Arguments const& argv) {
v8::HandleScope scope; v8::HandleScope scope;
TRI_v8_global_t* v8g; TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_primary_collection_t* primary = collection->_collection;
if (argv.Length() < 3 || argv.Length() > 4) { if (argv.Length() < 3 || argv.Length() > 4) {
return scope.Close(v8::ThrowException( return scope.Close(v8::ThrowException(
@ -933,17 +851,19 @@ static v8::Handle<v8::Value> SaveEdgeCol (TRI_vocbase_col_t const* collection,
"usage: save(<from>, <to>, <data>, <waitForSync>)"))); "usage: save(<from>, <to>, <data>, <waitForSync>)")));
} }
bool isBidirectional = false; ResourceHolder holder;
// set document key // set document key
TRI_voc_key_t key = 0; TRI_voc_key_t key = 0;
bool isBidirectional = false;
if (argv[2]->IsObject()) { if (argv[2]->IsObject()) {
v8::Handle<v8::Object> obj = argv[2]->ToObject(); v8::Handle<v8::Object> obj = argv[2]->ToObject();
v8::Handle<v8::Value> v = obj->Get(v8g->KeyKey); v8::Handle<v8::Value> v = obj->Get(v8g->KeyKey);
if (v->IsString()) { if (v->IsString()) {
TRI_Utf8ValueNFC str(TRI_CORE_MEM_ZONE, v); TRI_Utf8ValueNFC str(TRI_CORE_MEM_ZONE, v);
key = TRI_DuplicateString2(*str, str.length()); key = TRI_DuplicateString2(*str, str.length());
holder.registerString(TRI_CORE_MEM_ZONE, key);
} }
if (obj->Has(v8g->BidirectionalKey)) { if (obj->Has(v8g->BidirectionalKey)) {
@ -951,15 +871,11 @@ static v8::Handle<v8::Value> SaveEdgeCol (TRI_vocbase_col_t const* collection,
} }
} }
bool forceSync = false; const bool forceSync = (argv.Length() == 4 && TRI_ObjectToBoolean(argv[3]));
if (4 == argv.Length()) {
forceSync = TRI_ObjectToBoolean(argv[3]);
}
TRI_document_edge_t edge; TRI_document_edge_t edge;
edge._fromCid = trx->cid();
edge._fromCid = collection->_cid; edge._toCid = trx->cid();
edge._toCid = collection->_cid;
edge._toKey = 0; edge._toKey = 0;
edge._fromKey = 0; edge._fromKey = 0;
edge._isBidirectional = isBidirectional; edge._isBidirectional = isBidirectional;
@ -970,98 +886,39 @@ static v8::Handle<v8::Value> SaveEdgeCol (TRI_vocbase_col_t const* collection,
TRI_vocbase_col_t const* fromCollection = 0; TRI_vocbase_col_t const* fromCollection = 0;
TRI_voc_rid_t fromRid; TRI_voc_rid_t fromRid;
errMsg = TRI_ParseDocumentOrDocumentHandle(collection->_vocbase, fromCollection, edge._fromKey, fromRid, true, argv[0]); errMsg = TRI_ParseDocumentOrDocumentHandle(trx->vocbase(), fromCollection, edge._fromKey, fromRid, false, argv[0]);
holder.registerString(TRI_CORE_MEM_ZONE, edge._fromKey);
if (! errMsg.IsEmpty()) { if (! errMsg.IsEmpty()) {
if (fromCollection != 0) {
TRI_ReleaseCollection(fromCollection);
}
if (key) TRI_FreeString(TRI_CORE_MEM_ZONE, key);
if (edge._fromKey) TRI_FreeString(TRI_CORE_MEM_ZONE, edge._fromKey);
return scope.Close(v8::ThrowException(errMsg)); return scope.Close(v8::ThrowException(errMsg));
} }
edge._fromCid = fromCollection->_cid; edge._fromCid = fromCollection->_cid;
TRI_ReleaseCollection(fromCollection);
// extract to // extract to
TRI_vocbase_col_t const* toCollection = 0; TRI_vocbase_col_t const* toCollection = 0;
TRI_voc_rid_t toRid; TRI_voc_rid_t toRid;
errMsg = TRI_ParseDocumentOrDocumentHandle(collection->_vocbase, toCollection, edge._toKey, toRid, true, argv[1]); errMsg = TRI_ParseDocumentOrDocumentHandle(trx->vocbase(), toCollection, edge._toKey, toRid, false, argv[1]);
holder.registerString(TRI_CORE_MEM_ZONE, edge._toKey);
if (! errMsg.IsEmpty()) { if (! errMsg.IsEmpty()) {
if (toCollection != 0) {
TRI_ReleaseCollection(toCollection);
}
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
if (edge._fromKey) {
TRI_FreeString(TRI_CORE_MEM_ZONE, edge._fromKey);
}
if (edge._toKey) {
TRI_FreeString(TRI_CORE_MEM_ZONE, edge._toKey);
}
return scope.Close(v8::ThrowException(errMsg)); return scope.Close(v8::ThrowException(errMsg));
} }
edge._toCid = toCollection->_cid; edge._toCid = toCollection->_cid;
TRI_ReleaseCollection(toCollection);
// extract shaped data // extract shaped data
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[2], primary->_shaper); TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[2], trx->shaper());
if (! holder.registerShapedJson(trx->shaper(), shaped)) {
if (shaped == 0) {
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
if (edge._fromKey) {
TRI_FreeString(TRI_CORE_MEM_ZONE, edge._fromKey);
}
if (edge._toKey) {
TRI_FreeString(TRI_CORE_MEM_ZONE, edge._toKey);
}
return scope.Close(v8::ThrowException( return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_errno(), TRI_CreateErrorObject(TRI_errno(),
"<data> cannot be converted into JSON shape"))); "<data> cannot be converted into JSON shape")));
} }
// .............................................................................
// inside a write transaction
// .............................................................................
TRI_doc_operation_context_t context;
TRI_InitContextPrimaryCollection(&context, primary, TRI_DOC_UPDATE_ERROR, forceSync);
context._release = true;
primary->beginWrite(primary);
// the lock is freed in create
TRI_doc_mptr_t* document = 0; TRI_doc_mptr_t* document = 0;
int res = primary->create(&context, TRI_DOC_MARKER_KEY_EDGE, &document, shaped, &edge, key); int res = trx->createEdge(key, &document, shaped, forceSync, &edge);
// ............................................................................. res = trx->finish(res);
// outside a write transaction
// .............................................................................
TRI_FreeShapedJson(primary->_shaper, shaped);
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
if (edge._fromKey) {
TRI_FreeString(TRI_CORE_MEM_ZONE, edge._fromKey);
}
if (edge._toKey) {
TRI_FreeString(TRI_CORE_MEM_ZONE, edge._toKey);
}
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot save edge", true))); return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot save edge", true)));
@ -1070,7 +927,7 @@ static v8::Handle<v8::Value> SaveEdgeCol (TRI_vocbase_col_t const* collection,
assert(document); assert(document);
assert(document->_key); assert(document->_key);
string id = StringUtils::itoa(collection->_cid) + string(TRI_DOCUMENT_HANDLE_SEPARATOR_STR) + string(document->_key); string id = StringUtils::itoa(trx->cid()) + string(TRI_DOCUMENT_HANDLE_SEPARATOR_STR) + string(document->_key);
v8::Handle<v8::Object> result = v8::Object::New(); v8::Handle<v8::Object> result = v8::Object::New();
result->Set(v8g->DidKey, v8::String::New(id.c_str())); result->Set(v8g->DidKey, v8::String::New(id.c_str()));
@ -1101,19 +958,18 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (TRI_vocbase_t* vocbase,
"usage: update(<document>, <data>, <overwrite>, <keepnull>, <waitForSync>)"))); "usage: update(<document>, <data>, <overwrite>, <keepnull>, <waitForSync>)")));
} }
TRI_voc_key_t key = NULL; ResourceHolder holder;
TRI_voc_key_t key = 0;
TRI_voc_rid_t rid; TRI_voc_rid_t rid;
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, true, argv[0]); v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, true, argv[0]);
holder.registerString(TRI_CORE_MEM_ZONE, key);
if (! err.IsEmpty()) { if (! err.IsEmpty()) {
if (collection != 0) { if (collection != 0) {
TRI_ReleaseCollection(collection); TRI_ReleaseCollection(collection);
} }
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
return scope.Close(v8::ThrowException(err)); return scope.Close(v8::ThrowException(err));
} }
@ -1121,11 +977,8 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (TRI_vocbase_t* vocbase,
TRI_primary_collection_t* primary = collection->_collection; TRI_primary_collection_t* primary = collection->_collection;
TRI_json_t* json = TRI_JsonObject(argv[1]); TRI_json_t* json = TRI_JsonObject(argv[1]);
if (json == 0) { if (! holder.registerJson(TRI_UNKNOWN_MEM_ZONE, json)) {
TRI_ReleaseCollection(collection); TRI_ReleaseCollection(collection);
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
return scope.Close(v8::ThrowException( return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_errno(), TRI_CreateErrorObject(TRI_errno(),
"<data> is no valid JSON"))); "<data> is no valid JSON")));
@ -1186,11 +1039,10 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (TRI_vocbase_t* vocbase,
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, document->_data); TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, document->_data);
TRI_json_t* old = TRI_JsonShapedJson(primary->_shaper, &shapedJson); TRI_json_t* old = TRI_JsonShapedJson(primary->_shaper, &shapedJson);
if (old != 0) { if (holder.registerJson(primary->_shaper->_memoryZone, old)) {
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json, nullMeansRemove); TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json, nullMeansRemove);
TRI_FreeJson(primary->_shaper->_memoryZone, old);
if (patchedJson != 0) { if (holder.registerJson(TRI_UNKNOWN_MEM_ZONE, patchedJson)) {
TRI_doc_operation_context_t context; TRI_doc_operation_context_t context;
TRI_InitContextPrimaryCollection(&context, primary, policy, forceSync); TRI_InitContextPrimaryCollection(&context, primary, policy, forceSync);
@ -1199,14 +1051,8 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (TRI_vocbase_t* vocbase,
context._previousRid = &oldRid; context._previousRid = &oldRid;
res = primary->updateJson(&context, &document, patchedJson, key); res = primary->updateJson(&context, &document, patchedJson, key);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, patchedJson);
} }
} }
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
// ............................................................................. // .............................................................................
// outside a write transaction // outside a write transaction
@ -1249,17 +1095,18 @@ static v8::Handle<v8::Value> DeleteVocbaseCol (TRI_vocbase_t* vocbase,
"usage: delete(<document>, <overwrite>, <waitForSync>)"))); "usage: delete(<document>, <overwrite>, <waitForSync>)")));
} }
ResourceHolder holder;
TRI_voc_key_t key = 0; TRI_voc_key_t key = 0;
TRI_voc_rid_t rid; TRI_voc_rid_t rid;
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, true, argv[0]); v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, collection, key, rid, true, argv[0]);
holder.registerString(TRI_CORE_MEM_ZONE, key);
if (! err.IsEmpty()) { if (! err.IsEmpty()) {
if (collection != 0) { if (collection != 0) {
TRI_ReleaseCollection(collection); TRI_ReleaseCollection(collection);
} }
if (key) TRI_FreeString(TRI_CORE_MEM_ZONE, key);
return scope.Close(v8::ThrowException(err)); return scope.Close(v8::ThrowException(err));
} }
@ -1297,9 +1144,6 @@ static v8::Handle<v8::Value> DeleteVocbaseCol (TRI_vocbase_t* vocbase,
primary->beginWrite(primary); primary->beginWrite(primary);
int res = primary->destroy(&context, key); int res = primary->destroy(&context, key);
if (key) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
// ............................................................................. // .............................................................................
// outside a write transaction // outside a write transaction
@ -1567,15 +1411,14 @@ static v8::Handle<v8::Value> EnsureGeoIndexVocbaseCol (v8::Arguments const& argv
TRI_CreateErrorObject(TRI_errno(), "index could not be created", true))); TRI_CreateErrorObject(TRI_errno(), "index could not be created", true)));
} }
ResourceHolder holder;
TRI_json_t* json = idx->json(idx, primary); TRI_json_t* json = idx->json(idx, primary);
if (! holder.registerJson(TRI_UNKNOWN_MEM_ZONE, json)) {
if (! json) {
TRI_ReleaseCollection(collection); TRI_ReleaseCollection(collection);
return scope.Close(v8::ThrowException(v8::String::New("out of memory"))); return scope.Close(v8::ThrowException(v8::String::New("out of memory")));
} }
v8::Handle<v8::Value> index = IndexRep(&primary->base, json); v8::Handle<v8::Value> index = IndexRep(&primary->base, json);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
if (index->IsObject()) { if (index->IsObject()) {
index->ToObject()->Set(v8::String::New("isNewlyCreated"), created ? v8::True() : v8::False()); index->ToObject()->Set(v8::String::New("isNewlyCreated"), created ? v8::True() : v8::False());
@ -3590,9 +3433,14 @@ static v8::Handle<v8::Value> JS_EnsureCapConstraintVocbaseCol (v8::Arguments con
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_errno(), "index could not be created", true))); return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_errno(), "index could not be created", true)));
} }
ResourceHolder holder;
TRI_json_t* json = idx->json(idx, primary); TRI_json_t* json = idx->json(idx, primary);
if (! holder.registerJson(TRI_CORE_MEM_ZONE, json)) {
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_OUT_OF_MEMORY)));
}
v8::Handle<v8::Value> index = IndexRep(&primary->base, json); v8::Handle<v8::Value> index = IndexRep(&primary->base, json);
TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
if (index->IsObject()) { if (index->IsObject()) {
index->ToObject()->Set(v8::String::New("isNewlyCreated"), created ? v8::True() : v8::False()); index->ToObject()->Set(v8::String::New("isNewlyCreated"), created ? v8::True() : v8::False());
@ -4781,40 +4629,27 @@ static v8::Handle<v8::Value> JS_UpdateVocbaseCol (v8::Arguments const& argv) {
static v8::Handle<v8::Value> JS_SaveVocbaseCol (v8::Arguments const& argv) { static v8::Handle<v8::Value> JS_SaveVocbaseCol (v8::Arguments const& argv) {
v8::HandleScope scope; v8::HandleScope scope;
#ifdef TRI_ENABLE_TRX
TRI_vocbase_col_t* col = TRI_UnwrapClass<TRI_vocbase_col_t>(argv.Holder(), WRP_VOCBASE_COL_TYPE); TRI_vocbase_col_t* col = TRI_UnwrapClass<TRI_vocbase_col_t>(argv.Holder(), WRP_VOCBASE_COL_TYPE);
if (col == 0) {
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_INTERNAL)));
}
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type, false, "SaveVocBase"); SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type, false, "SaveVocBase");
v8::Handle<v8::Value> result;
int res = trx.begin(); int res = trx.begin();
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot save document", true))); return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot save document", true)));
} }
v8::Handle<v8::Value> result;
if ((TRI_col_type_e) col->_type == TRI_COL_TYPE_DOCUMENT) { if ((TRI_col_type_e) col->_type == TRI_COL_TYPE_DOCUMENT) {
result = SaveVocbaseCol(&trx, argv); result = SaveVocbaseCol(&trx, argv);
} }
else if ((TRI_col_type_e) col->_type == TRI_COL_TYPE_EDGE) {
#else result = SaveEdgeCol(&trx, argv);
v8::Handle<v8::Object> err;
TRI_vocbase_col_t const* collection = UseCollection(argv.Holder(), &err);
if (collection == 0) {
return scope.Close(v8::ThrowException(err));
} }
v8::Handle<v8::Value> result;
if (collection->_type == TRI_COL_TYPE_DOCUMENT) {
result = SaveVocbaseCol(collection, argv);
}
else if (collection->_type == TRI_COL_TYPE_EDGE) {
result = SaveEdgeCol(collection, argv);
}
TRI_ReleaseCollection(collection);
#endif
return scope.Close(result); return scope.Close(result);
} }
@ -5070,8 +4905,9 @@ static v8::Handle<v8::Value> JS_VersionVocbaseCol (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(v8::String::New("illegal collection pointer"))); return scope.Close(v8::ThrowException(v8::String::New("illegal collection pointer")));
} }
TRI_READ_LOCK_STATUS_VOCBASE_COL(collection);
TRI_col_info_t info; TRI_col_info_t info;
TRI_READ_LOCK_STATUS_VOCBASE_COL(collection);
int res = TRI_LoadCollectionInfo(collection->_path, &info); int res = TRI_LoadCollectionInfo(collection->_path, &info);
TRI_READ_UNLOCK_STATUS_VOCBASE_COL(collection); TRI_READ_UNLOCK_STATUS_VOCBASE_COL(collection);

View File

@ -30,6 +30,7 @@
#include "BasicsC/json.h" #include "BasicsC/json.h"
#include "BasicsC/strings.h" #include "BasicsC/strings.h"
#include "ShapedJson/json-shaper.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- class ResourceHolder // --SECTION-- class ResourceHolder
@ -58,7 +59,8 @@ class ResourceHolder {
typedef enum { typedef enum {
TYPE_STRING, TYPE_STRING,
TYPE_JSON TYPE_JSON,
TYPE_SHAPED_JSON
} }
resource_type_e; resource_type_e;
@ -68,20 +70,23 @@ class ResourceHolder {
struct Resource { struct Resource {
Resource (const resource_type_e type, Resource (const resource_type_e type,
TRI_memory_zone_t* const memoryZone, void* const context,
void* const value) : void* const value) :
_type(type), _type(type),
_memoryZone(memoryZone), _context(context),
_value(value) { _value(value) {
} }
~Resource () { ~Resource () {
switch (_type) { switch (_type) {
case TYPE_STRING: case TYPE_STRING:
TRI_FreeString(_memoryZone, (char*) _value); TRI_FreeString((TRI_memory_zone_t*) _context, (char*) _value);
break; break;
case TYPE_JSON: case TYPE_JSON:
TRI_FreeJson(_memoryZone, (TRI_json_t*) _value); TRI_FreeJson((TRI_memory_zone_t*) _context, (TRI_json_t*) _value);
break;
case TYPE_SHAPED_JSON:
TRI_FreeShapedJson((TRI_shaper_t*) _context, (TRI_shaped_json_t*) _value);
break; break;
default: { default: {
} }
@ -89,7 +94,7 @@ class ResourceHolder {
} }
resource_type_e _type; resource_type_e _type;
TRI_memory_zone_t* _memoryZone; void* _context;
void* _value; void* _value;
}; };
@ -150,18 +155,27 @@ class ResourceHolder {
/// @brief register a string object /// @brief register a string object
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool registerString (TRI_memory_zone_t* memoryZone, bool registerString (TRI_memory_zone_t* context,
char* const value) { char* const value) {
return registerResource(TYPE_STRING, memoryZone, (void*) value); return registerResource(TYPE_STRING, (void*) context, (void*) value);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief register a JSON object /// @brief register a JSON object
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool registerJson (TRI_memory_zone_t* memoryZone, bool registerJson (TRI_memory_zone_t* context,
TRI_json_t* const value) { TRI_json_t* const value) {
return registerResource(TYPE_JSON, memoryZone, (void*) value); return registerResource(TYPE_JSON, (void*) context, (void*) value);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register a shaped json object
////////////////////////////////////////////////////////////////////////////////
bool registerShapedJson (TRI_shaper_t* context,
TRI_shaped_json_t* const value) {
return registerResource(TYPE_SHAPED_JSON, (void*) context, (void*) value);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -184,13 +198,13 @@ class ResourceHolder {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool registerResource (const resource_type_e type, bool registerResource (const resource_type_e type,
TRI_memory_zone_t* memoryZone, void* const context,
void* const value) { void* const value) {
if (value == 0) { if (value == 0) {
return false; return false;
} }
Resource* resource = new Resource(type, memoryZone, value); Resource* resource = new Resource(type, context, value);
_resources.push_back(resource); _resources.push_back(resource);
return true; return true;