mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/triAGENS/ArangoDB into devel
This commit is contained in:
commit
3fb488c3a3
|
@ -439,7 +439,6 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) {
|
|||
|
||||
TRI_voc_cid_t cid = ca.cid();
|
||||
TRI_shaper_t* shaper = ca.shaper();
|
||||
//TRI_voc_did_t id = StringUtils::uint64(did);
|
||||
|
||||
// .............................................................................
|
||||
// inside read transaction
|
||||
|
@ -983,7 +982,6 @@ bool RestDocumentHandler::deleteDocument () {
|
|||
string key = suffix[1];
|
||||
|
||||
// extract document identifier
|
||||
//TRI_voc_did_t did = StringUtils::uint64(didStr);
|
||||
|
||||
// extract the revision
|
||||
TRI_voc_rid_t revision = extractRevision("if-match", "rev");
|
||||
|
|
|
@ -58,7 +58,6 @@ v8::Handle<v8::Value> TRI_ObjectReference (TRI_voc_cid_t cid, TRI_voc_key_t key)
|
|||
TRI_InitStringBuffer(&buffer, TRI_CORE_MEM_ZONE);
|
||||
TRI_AppendUInt64StringBuffer(&buffer, cid);
|
||||
TRI_AppendCharStringBuffer(&buffer, TRI_DOCUMENT_HANDLE_SEPARATOR_CHR);
|
||||
//TRI_AppendUInt64StringBuffer(&buffer, did);
|
||||
TRI_AppendStringStringBuffer(&buffer, (char*) key);
|
||||
|
||||
v8::Handle<v8::String> ref = v8::String::New(buffer._buffer);
|
||||
|
@ -68,42 +67,6 @@ v8::Handle<v8::Value> TRI_ObjectReference (TRI_voc_cid_t cid, TRI_voc_key_t key)
|
|||
return scope.Close(ref);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extratcs identifiers from a object reference
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IdentifiersObjectReference (v8::Handle<v8::Value> value, TRI_voc_cid_t& cid, TRI_voc_did_t& did) {
|
||||
bool error;
|
||||
|
||||
cid = 0;
|
||||
did = 0;
|
||||
|
||||
if (value->IsNumber() || value->IsNumberObject()) {
|
||||
did = (TRI_voc_did_t) TRI_ObjectToDouble(value, error);
|
||||
return ! error;
|
||||
}
|
||||
|
||||
string v = TRI_ObjectToString(value);
|
||||
|
||||
vector<string> doc = StringUtils::split(v, TRI_DOCUMENT_HANDLE_SEPARATOR_STR);
|
||||
|
||||
switch (doc.size()) {
|
||||
case 1:
|
||||
did = StringUtils::uint64(doc[1]);
|
||||
return did != 0;
|
||||
|
||||
case 2:
|
||||
cid = StringUtils::uint64(doc[0]);
|
||||
did = StringUtils::uint64(doc[1]);
|
||||
return cid != 0 && did != 0;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -52,12 +52,6 @@
|
|||
|
||||
v8::Handle<v8::Value> TRI_ObjectReference (TRI_voc_cid_t, TRI_voc_key_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extratcs identifiers from a object reference
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IdentifiersObjectReference (v8::Handle<v8::Value>, TRI_voc_cid_t&, TRI_voc_did_t&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -260,33 +260,6 @@ static bool IsDocumentHandle (v8::Handle<v8::Value> arg, TRI_voc_cid_t& cid, TRI
|
|||
TRI_v8_global_t* v8g;
|
||||
|
||||
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
/*
|
||||
if (arg->IsNumber()) {
|
||||
did = (TRI_voc_did_t) arg->ToNumber()->Value();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! arg->IsString()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TRI_Utf8ValueNFC str(TRI_UNKNOWN_MEM_ZONE, arg);
|
||||
char const* s = *str;
|
||||
|
||||
if (s == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
regmatch_t matches[3];
|
||||
|
||||
if (regexec(&v8g->DocumentIdRegex, s, sizeof(matches) / sizeof(matches[0]), matches, 0) == 0) {
|
||||
cid = TRI_UInt64String2(s + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
|
||||
did = TRI_UInt64String2(s + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
*/
|
||||
|
||||
if (! arg->IsString()) {
|
||||
return false;
|
||||
|
@ -304,7 +277,6 @@ static bool IsDocumentHandle (v8::Handle<v8::Value> arg, TRI_voc_cid_t& cid, TRI
|
|||
// "cid/key"
|
||||
if (regexec(&v8g->DocumentIdRegex, s, sizeof(matches) / sizeof(matches[0]), matches, 0) == 0) {
|
||||
cid = TRI_UInt64String2(s + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
|
||||
//did = TRI_UInt64String2(s + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
|
||||
key = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, s + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
|
||||
return true;
|
||||
}
|
||||
|
@ -2598,6 +2570,41 @@ static v8::Handle<v8::Value> JS_ParseAhuacatl (v8::Arguments const& argv) {
|
|||
static v8::Handle<v8::Value> JS_UpgradeVocbaseCol (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// some typedefs for deprecated markers, only used inside this function
|
||||
typedef uint64_t voc_did_t;
|
||||
|
||||
typedef struct {
|
||||
TRI_df_marker_t base;
|
||||
|
||||
voc_did_t _did; // this is the tick for a create, but not an update
|
||||
TRI_voc_rid_t _rid; // this is the tick for an create and update
|
||||
TRI_voc_eid_t _sid;
|
||||
|
||||
TRI_shape_sid_t _shape;
|
||||
}
|
||||
doc_document_marker_t_deprecated;
|
||||
|
||||
typedef struct {
|
||||
doc_document_marker_t_deprecated base;
|
||||
|
||||
TRI_voc_cid_t _toCid;
|
||||
voc_did_t _toDid;
|
||||
|
||||
TRI_voc_cid_t _fromCid;
|
||||
voc_did_t _fromDid;
|
||||
}
|
||||
doc_edge_marker_t_deprecated;
|
||||
|
||||
typedef struct {
|
||||
TRI_df_marker_t base;
|
||||
|
||||
voc_did_t _did; // this is the tick for a create, but not an update
|
||||
TRI_voc_rid_t _rid; // this is the tick for an create and update
|
||||
TRI_voc_eid_t _sid;
|
||||
}
|
||||
doc_deletion_marker_t_deprecated;
|
||||
|
||||
|
||||
if (argv.Length() != 0) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ILLEGAL_OPTION, "usage: upgrade()")));
|
||||
}
|
||||
|
@ -2731,13 +2738,13 @@ static v8::Handle<v8::Value> JS_UpgradeVocbaseCol (v8::Arguments const& argv) {
|
|||
|
||||
switch (marker._type) {
|
||||
case TRI_DOC_MARKER_DOCUMENT: {
|
||||
TRI_doc_document_marker_t_deprecated* oldMarker = (TRI_doc_document_marker_t_deprecated*) &payload;
|
||||
doc_document_marker_t_deprecated* oldMarker = (doc_document_marker_t_deprecated*) &payload;
|
||||
TRI_doc_document_key_marker_t newMarker;
|
||||
TRI_voc_size_t newMarkerSize = sizeof(TRI_doc_document_key_marker_t);
|
||||
|
||||
char* body = ((char*) oldMarker) + sizeof(TRI_doc_document_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySize = oldMarker->base._size - sizeof(TRI_doc_document_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySizePadded = paddedSize - sizeof(TRI_doc_document_marker_t_deprecated);
|
||||
char* body = ((char*) oldMarker) + sizeof(doc_document_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySize = oldMarker->base._size - sizeof(doc_document_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySizePadded = paddedSize - sizeof(doc_document_marker_t_deprecated);
|
||||
|
||||
char* keyBody = 0;
|
||||
TRI_voc_size_t keyBodySize = 0;
|
||||
|
@ -2777,13 +2784,13 @@ static v8::Handle<v8::Value> JS_UpgradeVocbaseCol (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
case TRI_DOC_MARKER_EDGE: {
|
||||
TRI_doc_edge_marker_t_deprecated* oldMarker = (TRI_doc_edge_marker_t_deprecated*) &payload;
|
||||
doc_edge_marker_t_deprecated* oldMarker = (doc_edge_marker_t_deprecated*) &payload;
|
||||
TRI_doc_edge_key_marker_t newMarker;
|
||||
TRI_voc_size_t newMarkerSize = sizeof(TRI_doc_edge_key_marker_t);
|
||||
|
||||
char* body = ((char*) oldMarker) + sizeof(TRI_doc_edge_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySize = oldMarker->base.base._size - sizeof(TRI_doc_edge_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySizePadded = paddedSize - sizeof(TRI_doc_edge_marker_t_deprecated);
|
||||
char* body = ((char*) oldMarker) + sizeof(doc_edge_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySize = oldMarker->base.base._size - sizeof(doc_edge_marker_t_deprecated);
|
||||
TRI_voc_size_t bodySizePadded = paddedSize - sizeof(doc_edge_marker_t_deprecated);
|
||||
|
||||
char* keyBody = 0;
|
||||
TRI_voc_size_t keyBodySize = 0;
|
||||
|
@ -2844,7 +2851,7 @@ static v8::Handle<v8::Value> JS_UpgradeVocbaseCol (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
case TRI_DOC_MARKER_DELETION: {
|
||||
TRI_doc_deletion_marker_t_deprecated* oldMarker = (TRI_doc_deletion_marker_t_deprecated*) &payload;
|
||||
doc_deletion_marker_t_deprecated* oldMarker = (doc_deletion_marker_t_deprecated*) &payload;
|
||||
TRI_doc_deletion_key_marker_t newMarker;
|
||||
TRI_voc_size_t newMarkerSize = sizeof(TRI_doc_deletion_key_marker_t);
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ static void ReleaseSimpleHeaders (TRI_headers_t* h, TRI_doc_mptr_t* header) {
|
|||
TRI_headers_t* TRI_CreateSimpleHeaders (size_t headerSize) {
|
||||
simple_headers_t* headers = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(simple_headers_t), false);
|
||||
|
||||
if (!headers) {
|
||||
if (headers == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,8 @@ void TRI_FreeIndex (TRI_index_t* const idx) {
|
|||
break;
|
||||
|
||||
case TRI_IDX_TYPE_PRIMARY_INDEX:
|
||||
TRI_FreePrimaryIndex(idx);
|
||||
TRI_DestroyPrimaryIndex(idx);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, idx);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -303,15 +304,6 @@ void TRI_DestroyPrimaryIndex (TRI_index_t* idx) {
|
|||
TRI_DestroyVectorString(&idx->_fields);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a primary index and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePrimaryIndex (TRI_index_t* idx) {
|
||||
TRI_DestroyPrimaryIndex(idx);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, idx);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -318,12 +318,6 @@ bool TRI_NeedsFullCoverageIndex (const TRI_index_t* const);
|
|||
|
||||
void TRI_DestroyPrimaryIndex (TRI_index_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a primary index and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePrimaryIndex (TRI_index_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -111,7 +111,6 @@ TRI_doc_update_policy_e;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_doc_mptr_s {
|
||||
//TRI_voc_did_t _did; // this is the document identifier
|
||||
TRI_voc_rid_t _rid; // this is the revision identifier
|
||||
TRI_voc_eid_t _eid; // this is the step identifier
|
||||
|
||||
|
@ -224,12 +223,12 @@ TRI_doc_collection_info_t;
|
|||
///
|
||||
/// As before, but instead of a shaped json a json object must be given.
|
||||
///
|
||||
/// @FUN{TRI_voc_did_t createLock (TRI_primary_collection_t*, TRI_df_marker_type_e, TRI_shaped_json_t const*)}
|
||||
/// @FUN{TRI_voc_key_t createLock (TRI_primary_collection_t*, TRI_df_marker_type_e, TRI_shaped_json_t const*)}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// As before, but the function will acquire and release the write lock.
|
||||
///
|
||||
/// @FUN{TRI_doc_mptr_t const read (TRI_primary_collection_t*, TRI_voc_did_t)}
|
||||
/// @FUN{TRI_doc_mptr_t const read (TRI_primary_collection_t*, TRI_voc_key_t)}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Returns the master pointer of the document with the given identifier. If the
|
||||
|
@ -237,7 +236,7 @@ TRI_doc_collection_info_t;
|
|||
/// the result is @LIT{0}. The function DOES NOT acquire or release a read
|
||||
/// lock. This must be done by the caller.
|
||||
///
|
||||
/// @FUN{TRI_doc_mptr_t const update (TRI_primary_collection_t*, TRI_shaped_json_t const*, TRI_voc_did_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e, bool @FA{release})}
|
||||
/// @FUN{TRI_doc_mptr_t const update (TRI_primary_collection_t*, TRI_shaped_json_t const*, TRI_voc_key_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e, bool @FA{release})}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Updates an existing document of the collection and returns copy of a valid
|
||||
|
@ -253,17 +252,17 @@ TRI_doc_collection_info_t;
|
|||
/// performed if the current revision matches the given. In any case the current
|
||||
/// revision after the updated of the document is returned in @FA{current}.
|
||||
///
|
||||
/// @FUN{TRI_doc_mptr_t const updateJson (TRI_primary_collection_t*, TRI_json_t const*, TRI_voc_did_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e, bool @FA{release})}
|
||||
/// @FUN{TRI_doc_mptr_t const updateJson (TRI_primary_collection_t*, TRI_json_t const*, TRI_voc_key_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e, bool @FA{release})}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// As before, but instead of a shaped json a json object must be given.
|
||||
///
|
||||
/// @FUN{int updateLock (TRI_primary_collection_t*, TRI_shaped_json_t const*, TRI_voc_did_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e)}
|
||||
/// @FUN{int updateLock (TRI_primary_collection_t*, TRI_shaped_json_t const*, TRI_voc_key_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e)}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// As before, but the function will acquire and release the write lock.
|
||||
///
|
||||
/// @FUN{int destroy (TRI_primary_collection_t*, TRI_voc_did_t, TRI_voc_rid_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e, bool @FA{release})}
|
||||
/// @FUN{int destroy (TRI_primary_collection_t*, TRI_voc_key_t, TRI_voc_rid_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e, bool @FA{release})}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Deletes an existing document from the given collection and returns @ref
|
||||
|
@ -278,7 +277,7 @@ TRI_doc_collection_info_t;
|
|||
/// valid revision of the document. If the delete was aborted, than @FA{current}
|
||||
/// contains the revision of the still alive document.
|
||||
///
|
||||
/// @FUN{int destroyLock (TRI_primary_collection_t*, TRI_voc_did_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e)}
|
||||
/// @FUN{int destroyLock (TRI_primary_collection_t*, TRI_voc_key_t, TRI_voc_rid_t @FA{rid}, TRI_voc_rid_t* @FA{current}, TRI_doc_update_policy_e)}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// As before, but the function will acquire and release the write lock.
|
||||
|
@ -334,36 +333,6 @@ typedef struct TRI_primary_collection_s {
|
|||
}
|
||||
TRI_primary_collection_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document datafile marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_doc_document_marker_s_deprecated {
|
||||
TRI_df_marker_t base;
|
||||
|
||||
TRI_voc_did_t _did; // this is the tick for a create, but not an update
|
||||
TRI_voc_rid_t _rid; // this is the tick for an create and update
|
||||
TRI_voc_eid_t _sid;
|
||||
|
||||
TRI_shape_sid_t _shape;
|
||||
}
|
||||
TRI_doc_document_marker_t_deprecated;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief edge datafile marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_doc_edge_marker_s_deprecated {
|
||||
TRI_doc_document_marker_t_deprecated base;
|
||||
|
||||
TRI_voc_cid_t _toCid;
|
||||
TRI_voc_did_t _toDid;
|
||||
|
||||
TRI_voc_cid_t _fromCid;
|
||||
TRI_voc_did_t _fromDid;
|
||||
}
|
||||
TRI_doc_edge_marker_t_deprecated;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document datafile marker with key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -401,19 +370,6 @@ TRI_doc_edge_key_marker_t;
|
|||
/// @brief document datafile deletion marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_doc_deletion_marker_s_deprecated {
|
||||
TRI_df_marker_t base;
|
||||
|
||||
TRI_voc_did_t _did; // this is the tick for a create, but not an update
|
||||
TRI_voc_rid_t _rid; // this is the tick for an create and update
|
||||
TRI_voc_eid_t _sid;
|
||||
}
|
||||
TRI_doc_deletion_marker_t_deprecated;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document datafile deletion marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_doc_deletion_key_marker_s {
|
||||
TRI_df_marker_t base;
|
||||
|
||||
|
|
|
@ -0,0 +1,419 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief primary index
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "primary-index.h"
|
||||
|
||||
#include "BasicsC/hashes.h"
|
||||
|
||||
#define INITIAL_SIZE (128)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the local id of the transaction that created a document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_transaction_local_id_t DocumentTransaction (const TRI_transaction_doc_mptr_t* const doc) {
|
||||
return doc->_validFrom;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether a specific transaction is currently running
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool InWriteTransactionsTable (const TRI_transaction_t* const trx,
|
||||
const TRI_transaction_local_id_t id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes the document key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashKey (const char* const key) {
|
||||
return TRI_FnvHashString(key);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check constraints on previous documnent revision found
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int CheckConstraint (TRI_revision_constraint_t* const constraint,
|
||||
const TRI_transaction_doc_mptr_t* const doc) {
|
||||
if (doc == NULL) {
|
||||
// document not found
|
||||
return TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (constraint != NULL) {
|
||||
// return revision id found
|
||||
constraint->_previousRevision = doc->_validFrom;
|
||||
|
||||
if (constraint->_policy == TRI_DOC_UPDATE_ERROR && constraint->_expectedRevision != doc->_validFrom) {
|
||||
// revision ids do not match
|
||||
return TRI_ERROR_ARANGO_CONFLICT;
|
||||
}
|
||||
else if (constraint->_policy == TRI_DOC_UPDATE_CONFLICT) {
|
||||
return TRI_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if (constraint->_policy == TRI_DOC_UPDATE_ILLEGAL) {
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compares a document key and a document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsVisible (const TRI_transaction_t* const trx,
|
||||
const char* const key,
|
||||
const TRI_transaction_doc_mptr_t* const element) {
|
||||
const TRI_transaction_local_id_t ownId = trx->_id._localId;
|
||||
|
||||
return (element->_validFrom < ownId) &&
|
||||
(! InWriteTransactionsTable(trx, element->_validFrom)) &&
|
||||
(element->_validTo == 0 || element->_validTo > ownId || InWriteTransactionsTable(trx, element->_validTo)) &&
|
||||
(strcmp(key, element->_key) == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief resizes the index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool Resize (TRI_primary_index_t* const idx) {
|
||||
TRI_transaction_doc_mptr_t** oldTable;
|
||||
uint64_t oldAlloc;
|
||||
uint64_t j;
|
||||
|
||||
oldTable = idx->_table;
|
||||
oldAlloc = idx->_nrAlloc;
|
||||
|
||||
idx->_nrAlloc = 2 * idx->_nrAlloc + 1;
|
||||
idx->_table = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, idx->_nrAlloc * sizeof(TRI_transaction_doc_mptr_t*), true);
|
||||
|
||||
if (idx->_table == NULL) {
|
||||
// out of memory
|
||||
idx->_nrAlloc = oldAlloc;
|
||||
idx->_table = oldTable;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// reposition old elements into new index
|
||||
for (j = 0; j < oldAlloc; ++j) {
|
||||
if (oldTable[j] != NULL) {
|
||||
const uint64_t hash = HashKey(oldTable[j]->_key);
|
||||
uint64_t i;
|
||||
|
||||
i = hash % idx->_nrAlloc;
|
||||
|
||||
while (idx->_table[i] != NULL) {
|
||||
i = (i + 1) % idx->_nrAlloc;
|
||||
}
|
||||
|
||||
idx->_table[i] = oldTable[j];
|
||||
}
|
||||
}
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, oldTable);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a document in the index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_transaction_doc_mptr_t* Lookup (TRI_primary_index_t* const idx,
|
||||
TRI_transaction_t* const trx,
|
||||
const char* const key) {
|
||||
const uint64_t hash = HashKey(key);
|
||||
uint64_t i;
|
||||
|
||||
i = hash % idx->_nrAlloc;
|
||||
|
||||
// search the table
|
||||
while (idx->_table[i] != NULL) {
|
||||
if (IsVisible(trx, key, idx->_table[i])) {
|
||||
return idx->_table[i];
|
||||
}
|
||||
|
||||
i = (i + 1) % idx->_nrAlloc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief insert a document into the index and return the previous revision
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_transaction_doc_mptr_t* Insert (TRI_primary_index_t* const idx,
|
||||
TRI_transaction_t* const trx,
|
||||
TRI_transaction_doc_mptr_t* const doc) {
|
||||
const uint64_t hash = HashKey(doc->_key);
|
||||
uint64_t i;
|
||||
TRI_transaction_doc_mptr_t* old;
|
||||
|
||||
if (idx->_nrAlloc == idx->_nrUsed) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i = hash % idx->_nrAlloc;
|
||||
|
||||
// search the table
|
||||
while (idx->_table[i] != NULL && ! IsVisible(trx, doc->_key, idx->_table[i])) {
|
||||
i = (i + 1) % idx->_nrAlloc;
|
||||
}
|
||||
|
||||
// get previous element
|
||||
old = idx->_table[i];
|
||||
if (old != NULL) {
|
||||
return old;
|
||||
}
|
||||
|
||||
idx->_table[i] = doc;
|
||||
idx->_nrUsed++;
|
||||
|
||||
// if we were adding and the table is more than half full, extend it
|
||||
if (idx->_nrAlloc < 2 * idx->_nrUsed) {
|
||||
Resize(idx);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_primary_index_t* TRI_CreatePrimaryIndex () {
|
||||
TRI_primary_index_t* idx;
|
||||
|
||||
idx = (TRI_primary_index_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_primary_index_t), false);
|
||||
if (idx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_InitReadWriteLock(&idx->_lock);
|
||||
|
||||
idx->_table = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_doc_mptr_t*) * INITIAL_SIZE, true);
|
||||
if (idx->_table == NULL) {
|
||||
// out of memory
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, idx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idx->_nrUsed = 0;
|
||||
idx->_nrAlloc = INITIAL_SIZE;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free the primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePrimaryIndex (TRI_primary_index_t* const idx) {
|
||||
assert(idx);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, &idx->_table);
|
||||
TRI_DestroyReadWriteLock(&idx->_lock);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, idx);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_transaction_doc_mptr_t* TRI_LookupPrimaryIndex (TRI_primary_index_t* const idx,
|
||||
TRI_transaction_t* const trx,
|
||||
const char* const key) {
|
||||
TRI_transaction_doc_mptr_t* old;
|
||||
|
||||
// start critical section -----------------------------
|
||||
TRI_ReadLockReadWriteLock(&idx->_lock);
|
||||
|
||||
old = Lookup(idx, trx, key);
|
||||
|
||||
// end critical section -----------------------------
|
||||
TRI_ReadUnlockReadWriteLock(&idx->_lock);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an element to the primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_InsertPrimaryIndex (TRI_primary_index_t* const idx,
|
||||
TRI_transaction_t* const trx,
|
||||
TRI_transaction_doc_mptr_t* const doc) {
|
||||
TRI_transaction_doc_mptr_t* old;
|
||||
const TRI_transaction_local_id_t id = TRI_LocalIdTransaction(trx);
|
||||
|
||||
assert(id == DocumentTransaction(doc));
|
||||
assert(doc->_validTo == 0);
|
||||
assert(doc->_data != NULL);
|
||||
|
||||
// start critical section -----------------------------
|
||||
TRI_WriteLockReadWriteLock(&idx->_lock);
|
||||
|
||||
old = Insert(idx, trx, doc);
|
||||
if (old != NULL) {
|
||||
// duplicate key error
|
||||
TRI_WriteUnlockReadWriteLock(&idx->_lock);
|
||||
|
||||
return TRI_ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED;
|
||||
}
|
||||
|
||||
// end critical section -----------------------------
|
||||
TRI_WriteUnlockReadWriteLock(&idx->_lock);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates an element in the primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_UpdatePrimaryIndex (TRI_primary_index_t* const idx,
|
||||
TRI_transaction_t* const trx,
|
||||
TRI_transaction_doc_mptr_t* const doc,
|
||||
TRI_revision_constraint_t* const constraint) {
|
||||
TRI_transaction_doc_mptr_t* old;
|
||||
const TRI_transaction_local_id_t id = TRI_LocalIdTransaction(trx);
|
||||
int result;
|
||||
|
||||
assert(id == DocumentTransaction(doc));
|
||||
assert(doc->_validTo == 0);
|
||||
assert(doc->_data != NULL);
|
||||
|
||||
// start critical section -----------------------------
|
||||
TRI_WriteLockReadWriteLock(&idx->_lock);
|
||||
|
||||
old = Lookup(idx, trx, doc->_key);
|
||||
|
||||
result = CheckConstraint(constraint, old);
|
||||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
// an error occurred
|
||||
// end critical section -----------------------------
|
||||
TRI_WriteUnlockReadWriteLock(&idx->_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// update previous revision
|
||||
assert(old);
|
||||
old->_validTo = id;
|
||||
|
||||
// end critical section -----------------------------
|
||||
TRI_WriteUnlockReadWriteLock(&idx->_lock);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an element from the primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_DeletePrimaryIndex (TRI_primary_index_t* const idx,
|
||||
TRI_transaction_t* const trx,
|
||||
TRI_transaction_doc_mptr_t* const doc,
|
||||
TRI_revision_constraint_t* const constraint) {
|
||||
TRI_transaction_doc_mptr_t* old;
|
||||
const TRI_transaction_local_id_t id = TRI_LocalIdTransaction(trx);
|
||||
int result;
|
||||
|
||||
assert(id == DocumentTransaction(doc));
|
||||
assert(doc->_validTo == 0);
|
||||
assert(doc->_data == NULL);
|
||||
|
||||
// start critical section -----------------------------
|
||||
TRI_WriteLockReadWriteLock(&idx->_lock);
|
||||
|
||||
old = Lookup(idx, trx, doc->_key);
|
||||
|
||||
result = CheckConstraint(constraint, old);
|
||||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
// an error occurred
|
||||
// end critical section -----------------------------
|
||||
TRI_WriteUnlockReadWriteLock(&idx->_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// update previous revision
|
||||
assert(old);
|
||||
old->_validTo = id;
|
||||
|
||||
// end critical section -----------------------------
|
||||
TRI_WriteUnlockReadWriteLock(&idx->_lock);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -0,0 +1,129 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief primary index of a collection
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_DURHAM_VOC_BASE_PRIMARY_INDEX_H
|
||||
#define TRIAGENS_DURHAM_VOC_BASE_PRIMARY_INDEX_H 1
|
||||
|
||||
#include "BasicsC/common.h"
|
||||
|
||||
#include "VocBase/primary-collection.h"
|
||||
#include "VocBase/transaction.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- PRIMARY INDEX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constraint container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_revision_constraint_s {
|
||||
TRI_doc_update_policy_e _policy;
|
||||
TRI_transaction_local_id_t _expectedRevision;
|
||||
TRI_transaction_local_id_t _previousRevision;
|
||||
}
|
||||
TRI_revision_constraint_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transactional master pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_doc_mptr_s {
|
||||
TRI_transaction_local_id_t _validFrom; // valid from trx id
|
||||
TRI_transaction_local_id_t _validTo; // valid to trx id
|
||||
char* _key; // document identifier (string)
|
||||
TRI_voc_fid_t _fid; // datafile identifier
|
||||
void const* _data; // pointer to the raw marker (NULL for deleted documents)
|
||||
}
|
||||
TRI_transaction_doc_mptr_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief primary index of a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_primary_index_s {
|
||||
TRI_read_write_lock_t _lock;
|
||||
|
||||
TRI_transaction_doc_mptr_t** _table;
|
||||
uint64_t _nrAlloc;
|
||||
uint64_t _nrUsed;
|
||||
}
|
||||
TRI_primary_index_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_primary_index_t* TRI_CreatePrimaryIndex (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free the primary index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreePrimaryIndex (TRI_primary_index_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -0,0 +1,736 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction subsystem
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "transaction.h"
|
||||
|
||||
#include "BasicsC/logging.h"
|
||||
#include "BasicsC/strings.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- TRANSACTION CONTEXT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type of the transaction as a string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char* TypeString (const TRI_transaction_type_e type) {
|
||||
switch (type) {
|
||||
case TRI_TRANSACTION_READ:
|
||||
return "read";
|
||||
case TRI_TRANSACTION_WRITE:
|
||||
return "write";
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the status of the transaction as a string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char* StatusString (const TRI_transaction_status_e status) {
|
||||
switch (status) {
|
||||
case TRI_TRANSACTION_CREATED:
|
||||
return "created";
|
||||
case TRI_TRANSACTION_RUNNING:
|
||||
return "running";
|
||||
case TRI_TRANSACTION_COMMITTED:
|
||||
return "committed";
|
||||
case TRI_TRANSACTION_ABORTED:
|
||||
return "aborted";
|
||||
case TRI_TRANSACTION_FINISHED:
|
||||
return "finished";
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate a transaction id
|
||||
/// The context lock must be held when calling this function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_transaction_local_id_t NextLocalTransactionId (TRI_transaction_context_t* const context) {
|
||||
TRI_transaction_local_id_t id;
|
||||
|
||||
id = ++context->_id._localId;
|
||||
return (TRI_transaction_local_id_t) id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a transaction in the global transactions list
|
||||
/// The context lock must be held when calling this function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int InsertTransactionList (TRI_transaction_list_t* const list,
|
||||
TRI_transaction_t* const trx) {
|
||||
const TRI_transaction_local_id_t id = trx->_id._localId;
|
||||
int res;
|
||||
TRI_transaction_list_entry_t entry;
|
||||
|
||||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
||||
entry._id = id;
|
||||
entry._status = TRI_TRANSACTION_RUNNING;
|
||||
|
||||
res = TRI_PushBackVector(&list->_vector, &entry);
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
++list->_numRunning;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locate a transaction in the global transactions list using a
|
||||
/// binary search
|
||||
/// The context lock must be held when calling this function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_transaction_list_entry_t* FindTransactionList (const TRI_transaction_list_t* const list,
|
||||
const TRI_transaction_local_id_t id,
|
||||
size_t* position) {
|
||||
|
||||
TRI_transaction_list_entry_t* entry;
|
||||
size_t l, r, n;
|
||||
|
||||
LOG_TRACE("looking up transaction %lu", (unsigned long) id);
|
||||
|
||||
n = list->_vector._length;
|
||||
if (n == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
r = n - 1;
|
||||
while (true) {
|
||||
const size_t i = l + ((r - l) / 2);
|
||||
|
||||
if (r < l) {
|
||||
// transaction not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry = (TRI_transaction_list_entry_t*) TRI_AtVector(&list->_vector, i);
|
||||
assert(entry);
|
||||
|
||||
if (entry->_id == id) {
|
||||
// found the transaction
|
||||
*position = i;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
if (entry->_id > id) {
|
||||
r = i - 1;
|
||||
}
|
||||
else {
|
||||
l = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove a transaction from the global transactions list
|
||||
/// The context lock must be held when calling this function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int RemoveTransactionList (TRI_transaction_list_t* const list,
|
||||
const TRI_transaction_local_id_t id) {
|
||||
TRI_transaction_list_entry_t* entry;
|
||||
size_t position;
|
||||
|
||||
entry = FindTransactionList(list, id, &position);
|
||||
if (entry == NULL) {
|
||||
// transaction not found, should not happen
|
||||
LOG_ERROR("logical error in transaction list");
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
assert(entry);
|
||||
|
||||
// update counters
|
||||
if (entry->_status == TRI_TRANSACTION_RUNNING) {
|
||||
--list->_numRunning;
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("logical error in transaction list");
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// remove it from the vector
|
||||
TRI_RemoveVector(&list->_vector, position);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove a transaction from the global transactions list
|
||||
/// The context lock must be held when calling this function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int UpdateTransactionList (TRI_transaction_list_t* const list,
|
||||
const TRI_transaction_local_id_t id,
|
||||
const TRI_transaction_status_e status) {
|
||||
TRI_transaction_list_entry_t* entry;
|
||||
size_t position;
|
||||
|
||||
assert(status == TRI_TRANSACTION_ABORTED);
|
||||
|
||||
entry = FindTransactionList(list, id, &position);
|
||||
if (entry == NULL) {
|
||||
// transaction not found, should not happen
|
||||
LOG_ERROR("logical error in transaction list");
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
// update counters
|
||||
if (entry->_status == TRI_TRANSACTION_RUNNING) {
|
||||
--list->_numRunning;
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("logical error in transaction list");
|
||||
}
|
||||
|
||||
if (status == TRI_TRANSACTION_ABORTED) {
|
||||
++list->_numAborted;
|
||||
}
|
||||
|
||||
entry->_status = status;
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialise a transactions list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void InitTransactionList (TRI_transaction_list_t* const list) {
|
||||
TRI_InitVector(&list->_vector, TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_list_entry_t));
|
||||
list->_numRunning = 0;
|
||||
list->_numAborted = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroy a transactions list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void DestroyTransactionList (TRI_transaction_list_t* const list) {
|
||||
TRI_DestroyVector(&list->_vector);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump the contents of a transaction list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void DumpTransactionList (const TRI_transaction_list_t* const list) {
|
||||
size_t i, n;
|
||||
|
||||
n = list->_vector._length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_transaction_list_entry_t* entry = TRI_AtVector(&list->_vector, i);
|
||||
|
||||
LOG_INFO("- trx: #%lu, status: %s",
|
||||
(unsigned long) entry->_id,
|
||||
StatusString(entry->_status));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the global transaction context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_transaction_context_t* TRI_CreateTransactionContext (TRI_transaction_server_id_t serverId) {
|
||||
TRI_transaction_context_t* context;
|
||||
|
||||
context = (TRI_transaction_context_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_context_t), false);
|
||||
if (context == NULL) {
|
||||
return context;
|
||||
}
|
||||
|
||||
TRI_InitMutex(&context->_lock);
|
||||
|
||||
InitTransactionList(&context->_readTransactions);
|
||||
InitTransactionList(&context->_writeTransactions);
|
||||
|
||||
context->_id._localId = 0;
|
||||
context->_id._serverId = serverId;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free the global transaction context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeTransactionContext (TRI_transaction_context_t* const context) {
|
||||
DestroyTransactionList(&context->_writeTransactions);
|
||||
DestroyTransactionList(&context->_readTransactions);
|
||||
|
||||
TRI_DestroyMutex(&context->_lock);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, context);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump transaction context data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DumpTransactionContext (TRI_transaction_context_t* const context) {
|
||||
TRI_LockMutex(&context->_lock);
|
||||
|
||||
LOG_INFO("transaction context, last-id: %lu:%lu",
|
||||
(unsigned long) context->_id._serverId,
|
||||
(unsigned long) context->_id._localId);
|
||||
|
||||
LOG_INFO("read transactions: numRunning: %lu, length: %lu, aborted: %lu",
|
||||
(unsigned long) context->_readTransactions._vector._length,
|
||||
(unsigned long) context->_readTransactions._numRunning,
|
||||
(unsigned long) context->_readTransactions._numAborted);
|
||||
|
||||
DumpTransactionList(&context->_readTransactions);
|
||||
|
||||
LOG_INFO("write transactions: numRunning: %lu, length: %lu, aborted: %lu",
|
||||
(unsigned long) context->_writeTransactions._vector._length,
|
||||
(unsigned long) context->_writeTransactions._numRunning,
|
||||
(unsigned long) context->_writeTransactions._numAborted);
|
||||
|
||||
DumpTransactionList(&context->_writeTransactions);
|
||||
|
||||
TRI_UnlockMutex(&context->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- TRANSACTION
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a transaction collection container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_transaction_collection_t* CreateCollection (const char* const name,
|
||||
const TRI_transaction_type_e type) {
|
||||
TRI_transaction_collection_t* collection;
|
||||
|
||||
collection = (TRI_transaction_collection_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_collection_t), false);
|
||||
if (collection == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
collection->_name = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, name);
|
||||
if (collection->_name == NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
collection->_type = type;
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free a transaction collection container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FreeCollection (TRI_transaction_collection_t* collection) {
|
||||
assert(collection);
|
||||
assert(collection->_name);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int RegisterTransaction (TRI_transaction_t* const trx) {
|
||||
TRI_transaction_context_t* context;
|
||||
TRI_transaction_list_t* list;
|
||||
int res;
|
||||
|
||||
assert(trx->_status == TRI_TRANSACTION_CREATED);
|
||||
assert(trx->_collections._length > 0);
|
||||
|
||||
context = trx->_context;
|
||||
|
||||
trx->_status = TRI_TRANSACTION_RUNNING;
|
||||
|
||||
if (trx->_type == TRI_TRANSACTION_READ) {
|
||||
// read-only transaction
|
||||
list = &context->_readTransactions;
|
||||
}
|
||||
else {
|
||||
list = &context->_writeTransactions;
|
||||
}
|
||||
|
||||
// start critical section -----------------------------------------
|
||||
TRI_LockMutex(&context->_lock);
|
||||
|
||||
trx->_id._localId = NextLocalTransactionId(context);
|
||||
res = InsertTransactionList(list, trx);
|
||||
|
||||
TRI_UnlockMutex(&context->_lock);
|
||||
// end critical section -----------------------------------------
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief update the status of a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int UpdateTransactionStatus (TRI_transaction_t* const trx,
|
||||
const TRI_transaction_status_e status) {
|
||||
const TRI_transaction_local_id_t id = trx->_id._localId;
|
||||
TRI_transaction_context_t* context;
|
||||
int res;
|
||||
|
||||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
||||
context = trx->_context;
|
||||
|
||||
// start critical section -----------------------------------------
|
||||
TRI_LockMutex(&context->_lock);
|
||||
|
||||
if (trx->_type == TRI_TRANSACTION_READ) {
|
||||
// read-only transactions cannot commit or roll-back
|
||||
assert(status == TRI_TRANSACTION_FINISHED);
|
||||
|
||||
LOG_TRACE("removing read transaction %lu", (unsigned long) id);
|
||||
res = RemoveTransactionList(&context->_readTransactions, id);
|
||||
}
|
||||
else {
|
||||
// write transactions
|
||||
|
||||
if (status == TRI_TRANSACTION_COMMITTED) {
|
||||
LOG_TRACE("removing write transaction %lu", (unsigned long) id);
|
||||
res = RemoveTransactionList(&context->_writeTransactions, id);
|
||||
}
|
||||
else if (status == TRI_TRANSACTION_ABORTED) {
|
||||
LOG_TRACE("updating write transaction %lu status %s", (unsigned long) id, StatusString(status));
|
||||
res = UpdateTransactionList(&context->_writeTransactions, id, status);
|
||||
}
|
||||
else {
|
||||
res = TRI_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&context->_lock);
|
||||
// end critical section -----------------------------------------
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
trx->_status = status;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a new transaction container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_transaction_t* TRI_CreateTransaction (TRI_transaction_context_t* const context,
|
||||
const TRI_transaction_isolation_level_e isolationLevel) {
|
||||
TRI_transaction_t* trx;
|
||||
|
||||
trx = (TRI_transaction_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_t), false);
|
||||
if (trx == NULL) {
|
||||
// out of memory
|
||||
return NULL;
|
||||
}
|
||||
|
||||
trx->_context = context;
|
||||
trx->_id._serverId = context->_id._serverId;
|
||||
trx->_id._localId = 0;
|
||||
trx->_status = TRI_TRANSACTION_CREATED;
|
||||
trx->_type = TRI_TRANSACTION_READ;
|
||||
trx->_isolationLevel = isolationLevel;
|
||||
|
||||
TRI_InitVectorPointer(&trx->_collections, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
return trx;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free a transaction container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeTransaction (TRI_transaction_t* const trx) {
|
||||
size_t i;
|
||||
|
||||
assert(trx);
|
||||
|
||||
if (trx->_status == TRI_TRANSACTION_RUNNING) {
|
||||
TRI_AbortTransaction(trx);
|
||||
}
|
||||
|
||||
// free all collections
|
||||
i = trx->_collections._length;
|
||||
while (i-- > 0) {
|
||||
TRI_transaction_collection_t* collection = TRI_AtVectorPointer(&trx->_collections, i);
|
||||
|
||||
FreeCollection(collection);
|
||||
if (i == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_DestroyVectorPointer(&trx->_collections);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, trx);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the local id of a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_transaction_local_id_t TRI_LocalIdTransaction (const TRI_transaction_t* const trx) {
|
||||
return trx->_id._localId;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump information about a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DumpTransaction (TRI_transaction_t* const trx) {
|
||||
size_t i, n;
|
||||
|
||||
LOG_INFO("transaction id: %lu:%lu, type: %s, status: %s",
|
||||
(unsigned long) trx->_id._serverId,
|
||||
(unsigned long) trx->_id._localId,
|
||||
TypeString(trx->_type),
|
||||
StatusString(trx->_status));
|
||||
|
||||
n = trx->_collections._length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_transaction_collection_t* collection = TRI_AtVectorPointer(&trx->_collections, i);
|
||||
|
||||
LOG_INFO("- collection: %s, type: %s", collection->_name, TypeString(collection->_type));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a collection to a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_AddCollectionTransaction (TRI_transaction_t* const trx,
|
||||
const char* const name,
|
||||
const TRI_transaction_type_e type) {
|
||||
TRI_transaction_collection_t* collection;
|
||||
size_t i, n;
|
||||
|
||||
assert(trx->_status == TRI_TRANSACTION_CREATED);
|
||||
assert(name);
|
||||
|
||||
// upgrade transaction type if required
|
||||
if (type == TRI_TRANSACTION_WRITE && trx->_type == TRI_TRANSACTION_READ) {
|
||||
trx->_type = TRI_TRANSACTION_WRITE;
|
||||
}
|
||||
|
||||
// check if we already have got this collection in the vector
|
||||
n = trx->_collections._length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
int res;
|
||||
|
||||
collection = TRI_AtVectorPointer(&trx->_collections, i);
|
||||
res = strcmp(name, collection->_name);
|
||||
|
||||
if (res < 0) {
|
||||
collection = CreateCollection(name, type);
|
||||
if (collection == NULL) {
|
||||
// out of memory
|
||||
return false;
|
||||
}
|
||||
|
||||
TRI_InsertVectorPointer(&trx->_collections, collection, i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
// collection is already contained in vector
|
||||
|
||||
// upgrade collection type if required
|
||||
if (type == TRI_TRANSACTION_WRITE && collection->_type == TRI_TRANSACTION_READ) {
|
||||
collection->_type = TRI_TRANSACTION_WRITE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// collection was not contained. now insert it
|
||||
collection = CreateCollection(name, type);
|
||||
if (collection == NULL) {
|
||||
// out of memory
|
||||
return false;
|
||||
}
|
||||
|
||||
TRI_PushBackVectorPointer(&trx->_collections, collection);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief start a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_StartTransaction (TRI_transaction_t* const trx) {
|
||||
int res;
|
||||
assert(trx->_status == TRI_TRANSACTION_CREATED);
|
||||
|
||||
res = RegisterTransaction(trx);
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
trx->_status = TRI_TRANSACTION_RUNNING;
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief commit a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_CommitTransaction (TRI_transaction_t* const trx) {
|
||||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
||||
return UpdateTransactionStatus(trx, TRI_TRANSACTION_COMMITTED);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief abort a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_AbortTransaction (TRI_transaction_t* const trx) {
|
||||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
||||
return UpdateTransactionStatus(trx, TRI_TRANSACTION_ABORTED);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief finish a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_FinishTransaction (TRI_transaction_t* const trx) {
|
||||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
||||
if (trx->_type == TRI_TRANSACTION_READ) {
|
||||
// read transactions
|
||||
return UpdateTransactionStatus(trx, TRI_TRANSACTION_FINISHED);
|
||||
}
|
||||
else {
|
||||
// write transactions
|
||||
return UpdateTransactionStatus(trx, TRI_TRANSACTION_COMMITTED);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -0,0 +1,356 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction subsystem
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_DURHAM_VOC_BASE_TRANSACTION_H
|
||||
#define TRIAGENS_DURHAM_VOC_BASE_TRANSACTION_H 1
|
||||
|
||||
#include "BasicsC/common.h"
|
||||
#include "BasicsC/locks.h"
|
||||
#include "BasicsC/vector.h"
|
||||
#include "BasicsC/voc-errors.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- TRANSACTION TYPES
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief local transaction id typedef
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef uint64_t TRI_transaction_local_id_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief server identifier type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef uint16_t TRI_transaction_server_id_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction id typedef
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_id_s {
|
||||
TRI_transaction_local_id_t _localId;
|
||||
TRI_transaction_server_id_t _serverId;
|
||||
}
|
||||
TRI_transaction_id_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction isolation level
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
TRI_TRANSACTION_READ_UNCOMMITED = 1,
|
||||
TRI_TRANSACTION_READ_COMMITTED = 2,
|
||||
TRI_TRANSACTION_READ_REPEATABLE = 3
|
||||
}
|
||||
TRI_transaction_isolation_level_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
TRI_TRANSACTION_READ = 1,
|
||||
TRI_TRANSACTION_WRITE = 2
|
||||
}
|
||||
TRI_transaction_type_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction statuses
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
TRI_TRANSACTION_CREATED = 0,
|
||||
TRI_TRANSACTION_RUNNING = 1,
|
||||
TRI_TRANSACTION_COMMITTED = 2,
|
||||
TRI_TRANSACTION_ABORTED = 3,
|
||||
TRI_TRANSACTION_FINISHED = 4
|
||||
}
|
||||
TRI_transaction_status_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- TRANSACTION LIST
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief an entry in the transactions list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_list_entry_s {
|
||||
TRI_transaction_local_id_t _id;
|
||||
TRI_transaction_status_e _status;
|
||||
}
|
||||
TRI_transaction_list_entry_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction list typedef
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_list_s {
|
||||
TRI_vector_t _vector; // vector containing trx_list_entry_t
|
||||
size_t _numRunning; // number of currently running trx
|
||||
size_t _numAborted; // number of already aborted trx
|
||||
}
|
||||
TRI_transaction_list_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- TRANSACTION CONTEXT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction context typedef
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_context_s {
|
||||
TRI_transaction_id_t _id;
|
||||
TRI_mutex_t _lock;
|
||||
TRI_transaction_list_t _readTransactions;
|
||||
TRI_transaction_list_t _writeTransactions;
|
||||
}
|
||||
TRI_transaction_context_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the global transaction context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_transaction_context_t* TRI_CreateTransactionContext (TRI_transaction_server_id_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free the global transaction context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeTransactionContext (TRI_transaction_context_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DumpTransactionContext (TRI_transaction_context_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- TRANSACTION
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection used in a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_collection_s {
|
||||
const char* _name;
|
||||
TRI_transaction_type_e _type;
|
||||
// locks and pointers go here
|
||||
}
|
||||
TRI_transaction_collection_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transaction typedef
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_s {
|
||||
TRI_transaction_context_t* _context;
|
||||
TRI_transaction_id_t _id;
|
||||
TRI_transaction_type_e _type;
|
||||
TRI_transaction_status_e _status;
|
||||
TRI_transaction_isolation_level_e _isolationLevel;
|
||||
|
||||
TRI_vector_pointer_t _collections;
|
||||
}
|
||||
TRI_transaction_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a new transaction container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_transaction_t* TRI_CreateTransaction (TRI_transaction_context_t* const,
|
||||
const TRI_transaction_isolation_level_e);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free a transaction container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeTransaction (TRI_transaction_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the local id of a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_transaction_local_id_t TRI_LocalIdTransaction (const TRI_transaction_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump information about a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DumpTransaction (TRI_transaction_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a collection to a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_AddCollectionTransaction (TRI_transaction_t* const,
|
||||
const char* const,
|
||||
const TRI_transaction_type_e);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief start a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_StartTransaction (TRI_transaction_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief commit a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_CommitTransaction (TRI_transaction_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief abort a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_AbortTransaction (TRI_transaction_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief finish a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_FinishTransaction (TRI_transaction_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -277,12 +277,6 @@ typedef uint64_t TRI_voc_cid_t;
|
|||
|
||||
typedef uint64_t TRI_voc_fid_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document identifier type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef uint64_t TRI_voc_did_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document key identifier type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue