1
0
Fork 0

Merge branch 'sharding' of ssh://github.com/triAGENS/ArangoDB into sharding

This commit is contained in:
Max Neunhoeffer 2014-02-28 18:51:24 +01:00
commit 944f29deb0
30 changed files with 613 additions and 424 deletions

View File

@ -1,6 +1,24 @@
v2.0.0-alpha1 (2014-02-28)
--------------------------
* added sharding :-)
* INCOMPATIBLE CHANGE: using complex values in AQL filter conditions with operators other
than equality (e.g. >=, >, <=, <) will disable usage of skiplist indexes for filter
evaluation.
For example, the following queries will be affected by change:
FOR doc IN docs FILTER doc.value < { foo: "bar" } RETURN doc
FOR doc IN docs FILTER doc.value >= [ 1, 2, 3 ] RETURN doc
The following queries will not be affected by the change:
FOR doc IN docs FILTER doc.value == 1 RETURN doc
FOR doc IN docs FILTER doc.value == "foo" RETURN doc
FOR doc IN docs FILTER doc.value == [ 1, 2, 3 ] RETURN doc
FOR doc IN docs FILTER doc.value == { foo: "bar" } RETURN doc
* added explicit startup parameter `--server.reuse-address`
* removed undocumented REST API method GET `/_admin/database-name`

View File

@ -452,6 +452,31 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
continue;
}
if (candidate->_type == TRI_AQL_ACCESS_RANGE_SINGLE) {
// range type. check if the compare value is a list or an object
TRI_json_t* value = candidate->_value._singleRange._value;
if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) {
// list or object, we cannot use this for comparison in a skiplist
continue;
}
}
else if (candidate->_type == TRI_AQL_ACCESS_RANGE_DOUBLE) {
// range type. check if the compare value is a list or an object
TRI_json_t* value = candidate->_value._between._lower._value;
if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) {
// list or object, we cannot use this for comparison in a skiplist
continue;
}
value = candidate->_value._between._upper._value;
if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) {
// list or object, we cannot use this for comparison in a skiplist
continue;
}
}
lastTypeWasExact = candidateIsExact;
TRI_PushBackVectorPointer(&matches, candidate);

View File

@ -161,8 +161,7 @@ void TRI_ClearIndexOperator(TRI_index_operator_t* indexOperator) {
case TRI_GT_INDEX_OPERATOR:
case TRI_NE_INDEX_OPERATOR:
case TRI_LE_INDEX_OPERATOR:
case TRI_LT_INDEX_OPERATOR:
case TRI_IN_INDEX_OPERATOR: {
case TRI_LT_INDEX_OPERATOR: {
relationOperator = (TRI_relation_index_operator_t*)(indexOperator);
if (relationOperator->_parameters != NULL) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, relationOperator->_parameters);
@ -233,9 +232,7 @@ TRI_index_operator_t* TRI_CopyIndexOperator(TRI_index_operator_t* indexOperator)
case TRI_GT_INDEX_OPERATOR:
case TRI_NE_INDEX_OPERATOR:
case TRI_LE_INDEX_OPERATOR:
case TRI_LT_INDEX_OPERATOR:
case TRI_IN_INDEX_OPERATOR: {
case TRI_LT_INDEX_OPERATOR: {
oldRelationOperator = (TRI_relation_index_operator_t*)(indexOperator);
newRelationOperator = (TRI_relation_index_operator_t*) (TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_relation_index_operator_t), false));

View File

@ -59,7 +59,6 @@ typedef enum {
TRI_LT_INDEX_OPERATOR,
TRI_GE_INDEX_OPERATOR,
TRI_GT_INDEX_OPERATOR,
TRI_IN_INDEX_OPERATOR,
TRI_AND_INDEX_OPERATOR,
TRI_NOT_INDEX_OPERATOR,

View File

@ -268,7 +268,7 @@ int Syncer::applyCollectionDumpMarker (TRI_transaction_collection_t* trxCollecti
TRI_primary_collection_t* primary = trxCollection->_collection->_collection;
TRI_memory_zone_t* zone = primary->_shaper->_memoryZone;
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(primary->_shaper, json);
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(primary->_shaper, json, true, true);
if (shaped != 0) {
TRI_doc_mptr_t mptr;

View File

@ -1895,7 +1895,7 @@ int RestReplicationHandler::applyCollectionDumpMarker (CollectionNameResolver co
TRI_primary_collection_t* primary = trxCollection->_collection->_collection;
TRI_memory_zone_t* zone = primary->_shaper->_memoryZone;
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(primary->_shaper, json);
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(primary->_shaper, json, true, true);
if (shaped != 0) {
TRI_doc_mptr_t mptr;

View File

@ -207,7 +207,7 @@ static int CmpElmElm(void* sli, void* left, void* right,
/// @brief compares a key with an element in a skip list, generic callback
////////////////////////////////////////////////////////////////////////////////
static int CmpKeyElm(void* sli, void* left, void* right) {
static int CmpKeyElm (void* sli, void* left, void* right) {
SkiplistIndex* skiplistindex = sli;
TRI_skiplist_index_key_t* leftKey = left;

View File

@ -844,7 +844,7 @@ namespace triagens {
TRI_shaper_t* shaper = this->shaper(trxCollection);
TRI_memory_zone_t* zone = shaper->_memoryZone;
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(shaper, json);
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(shaper, json, true, isLocked(trxCollection, TRI_TRANSACTION_WRITE));
if (shaped == 0) {
return TRI_ERROR_ARANGO_SHAPER_FAILED;
@ -909,7 +909,7 @@ namespace triagens {
TRI_shaper_t* shaper = this->shaper(trxCollection);
TRI_memory_zone_t* zone = shaper->_memoryZone;
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(shaper, json);
TRI_shaped_json_t* shaped = TRI_ShapedJsonJson(shaper, json, true, isLocked(trxCollection, TRI_TRANSACTION_WRITE));
if (shaped == 0) {
return TRI_ERROR_ARANGO_SHAPER_FAILED;

View File

@ -122,6 +122,21 @@ query_t;
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief return an empty result set
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> EmptyResult () {
v8::HandleScope scope;
v8::Handle<v8::Object> result = v8::Object::New();
result->Set(v8::String::New("documents"), v8::Array::New());
result->Set(v8::String::New("total"), v8::Number::New(0));
result->Set(v8::String::New("count"), v8::Number::New(0));
return scope.Close(result);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extracts skip and limit
////////////////////////////////////////////////////////////////////////////////
@ -212,7 +227,7 @@ static void CleanupExampleObject (TRI_memory_zone_t* zone,
/// @brief sets up the example object
////////////////////////////////////////////////////////////////////////////////
static int SetupExampleObject (v8::Handle<v8::Object> example,
static int SetupExampleObject (v8::Handle<v8::Object> const& example,
TRI_shaper_t* shaper,
size_t& n,
TRI_shape_pid_t*& pids,
@ -250,8 +265,15 @@ static int SetupExampleObject (v8::Handle<v8::Object> example,
TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key);
if (*keyStr != 0) {
pids[i] = shaper->findAttributePathByName(shaper, *keyStr);
values[i] = TRI_ShapedJsonV8Object(val, shaper);
pids[i] = shaper->lookupAttributePathByName(shaper, *keyStr);
if (pids[i] == 0) {
// no attribute path found. this means the result will be empty
CleanupExampleObject(shaper->_memoryZone, i, pids, values);
return TRI_RESULT_ELEMENT_NOT_FOUND;
}
values[i] = TRI_ShapedJsonV8Object(val, shaper, false, false);
}
if (*keyStr == 0 || pids[i] == 0 || values[i] == 0) {
@ -951,6 +973,8 @@ static int SetupSearchValue (TRI_vector_t const* paths,
// convert
for (size_t i = 0; i < n; ++i) {
TRI_shape_pid_t pid = * (TRI_shape_pid_t*) TRI_AtVector(paths, i);
assert(pid != 0);
char const* name = TRI_AttributeNameShapePid(shaper, pid);
if (name == NULL) {
@ -965,15 +989,18 @@ static int SetupSearchValue (TRI_vector_t const* paths,
if (example->HasOwnProperty(key)) {
v8::Handle<v8::Value> val = example->Get(key);
res = TRI_FillShapedJsonV8Object(val, &result._values[i], shaper);
res = TRI_FillShapedJsonV8Object(val, &result._values[i], shaper, false, false);
}
else {
res = TRI_FillShapedJsonV8Object(v8::Null(), &result._values[i], shaper);
res = TRI_FillShapedJsonV8Object(v8::Null(), &result._values[i], shaper, false, false);
}
if (res != TRI_ERROR_NO_ERROR) {
DestroySearchValue(shaper->_memoryZone, result);
*err = TRI_CreateErrorObject(res, "cannot convert value to JSON");
if (res != TRI_RESULT_ELEMENT_NOT_FOUND) {
*err = TRI_CreateErrorObject(res, "cannot convert value to JSON");
}
return res;
}
}
@ -1078,6 +1105,11 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
TRI_skiplist_iterator_t* skiplistIterator = TRI_LookupSkiplistIndex(idx, skiplistOperator);
if (skiplistIterator == 0) {
int res = TRI_errno();
if (res == TRI_RESULT_ELEMENT_NOT_FOUND) {
return scope.Close(EmptyResult());
}
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_NO_INDEX);
}
@ -1953,6 +1985,11 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
v8::Handle<v8::Object> err;
res = SetupExampleObject(example, shaper, n, pids, values, &err);
if (res == TRI_RESULT_ELEMENT_NOT_FOUND) {
// empty result
return scope.Close(EmptyResult());
}
if (res != TRI_ERROR_NO_ERROR) {
return scope.Close(v8::ThrowException(err));
}
@ -2085,6 +2122,10 @@ static v8::Handle<v8::Value> ByExampleHashIndexQuery (ReadTransactionType& trx,
int res = SetupSearchValue(&hashIndex->_paths, example, shaper, searchValue, err);
if (res != TRI_ERROR_NO_ERROR) {
if (res == TRI_RESULT_ELEMENT_NOT_FOUND) {
return scope.Close(EmptyResult());
}
return scope.Close(v8::ThrowException(*err));
}

View File

@ -2465,6 +2465,11 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (bool useCollection,
TRI_memory_zone_t* zone = primary->_shaper->_memoryZone;
TRI_doc_mptr_t document;
// we must lock here, because below we are
// - reading the old document in coordinator case
// - creating a shape, which might trigger a write into the collection
trx.lockWrite();
#ifdef TRI_ENABLE_CLUSTER
if (ServerState::instance()->isDBserver()) {
@ -2478,7 +2483,6 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (bool useCollection,
TRI_V8_EXCEPTION_MEMORY(scope);
}
trx.lockWrite();
res = trx.read(&document, key);
if (res != TRI_ERROR_NO_ERROR || document._key == 0 || document._data == 0) {
@ -2509,8 +2513,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (bool useCollection,
}
#endif
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[1], primary->_shaper);
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[1], primary->_shaper, true, true);
if (shaped == 0) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
@ -2575,12 +2578,13 @@ static v8::Handle<v8::Value> SaveVocbaseCol (
TRI_primary_collection_t* primary = trx->primaryCollection();
TRI_memory_zone_t* zone = primary->_shaper->_memoryZone;
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[0], primary->_shaper);
trx->lockWrite();
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[0], primary->_shaper, true, true);
if (shaped == 0) {
if (key != 0) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
FREE_STRING(TRI_CORE_MEM_ZONE, key);
TRI_V8_EXCEPTION_MESSAGE(scope, TRI_errno(), "<data> cannot be converted into JSON shape");
}
@ -2593,9 +2597,7 @@ static v8::Handle<v8::Value> SaveVocbaseCol (
TRI_FreeShapedJson(zone, shaped);
if (key != 0) {
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
}
FREE_STRING(TRI_CORE_MEM_ZONE, key);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION(scope, res);
@ -2695,8 +2697,9 @@ static v8::Handle<v8::Value> SaveEdgeCol (
TRI_primary_collection_t* primary = trx->primaryCollection();
TRI_memory_zone_t* zone = primary->_shaper->_memoryZone;
trx->lockWrite();
// extract shaped data
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[2], primary->_shaper);
TRI_shaped_json_t* shaped = TRI_ShapedJsonV8Object(argv[2], primary->_shaper, true, true);
if (shaped == 0) {
FREE_STRING(TRI_CORE_MEM_ZONE, edge._fromKey);
@ -10065,7 +10068,11 @@ static v8::Handle<v8::Integer> PropertyQueryShapedJson (v8::Local<v8::String> na
// get shape accessor
TRI_shaper_t* shaper = collection->_shaper;
TRI_shape_pid_t pid = shaper->findAttributePathByName(shaper, key.c_str());
TRI_shape_pid_t pid = shaper->lookupAttributePathByName(shaper, key.c_str());
if (pid == 0) {
return scope.Close(v8::Handle<v8::Integer>());
}
TRI_shape_sid_t sid;
TRI_EXTRACT_SHAPE_IDENTIFIER_MARKER(sid, marker);

View File

@ -118,7 +118,11 @@ static char* ExtractStringShapedJson (TRI_shaper_t* shaper,
bool ok;
char* result;
pid = shaper->findAttributePathByName(shaper, path);
pid = shaper->lookupAttributePathByName(shaper, path);
if (pid == 0) {
return NULL;
}
ok = TRI_ExtractShapedJsonVocShaper(shaper, document, 0, pid, &shaped, &shape);
@ -165,7 +169,12 @@ static bool ExtractBooleanShapedJson (TRI_shaper_t* shaper,
*found = false;
}
pid = shaper->findAttributePathByName(shaper, path);
pid = shaper->lookupAttributePathByName(shaper, path);
if (pid == 0) {
return false;
}
ok = TRI_ExtractShapedJsonVocShaper(shaper, document, 0, pid, &shaped, &shape);
if (! ok || shape == NULL) {

View File

@ -1214,21 +1214,23 @@ int TRI_WriteElementDatafile (TRI_datafile_t* datafile,
#ifdef TRI_ENABLE_MAINTAINER_MODE
// check _tick value of marker and set min/max tick values for datafile
if (tick <= datafile->_tickMin || tick <= (TRI_voc_tick_t) datafile->_fid) {
LOG_WARNING("logic error. invalid tick value %llu encountered when writing marker of type %d into datafile '%s'. "
LOG_FATAL_AND_EXIT("logic error. invalid tick value %llu encountered when writing marker of type %d into datafile '%s'. "
"expected tick value > tickMin %llu",
(unsigned long long) tick,
(int) marker->_type,
datafile->getName(datafile),
(unsigned long long) datafile->_tickMin);
assert(false);
}
if (tick <= datafile->_tickMax) {
LOG_WARNING("logic error. invalid tick value %llu encountered when writing marker of type %d into datafile '%s'. "
LOG_FATAL_AND_EXIT("logic error. invalid tick value %llu encountered when writing marker of type %d into datafile '%s'. "
"expected tick value > tickMax %llu",
(unsigned long long) tick,
(int) marker->_type,
datafile->getName(datafile),
(unsigned long long) datafile->_tickMax);
assert(false);
}
#endif

View File

@ -4210,11 +4210,12 @@ bool TRI_DropIndex2DocumentCollection (TRI_document_collection_t* document,
/// freed.
////////////////////////////////////////////////////////////////////////////////
int TRI_PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes,
TRI_shaper_t* shaper,
TRI_vector_t* pids,
TRI_vector_pointer_t* names,
bool sorted) {
static int PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes,
TRI_shaper_t* shaper,
TRI_vector_t* pids,
TRI_vector_pointer_t* names,
bool sorted,
bool create) {
pid_name_t* pidnames;
size_t j;
@ -4223,17 +4224,23 @@ int TRI_PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes,
// .............................................................................
if (sorted) {
// combine name and pid
pidnames = TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(pid_name_t) * attributes->_length, false);
if (pidnames == NULL) {
LOG_ERROR("out of memory in TRI_PidNamesByAttributeNames");
LOG_ERROR("out of memory in PidNamesByAttributeNames");
return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
}
for (j = 0; j < attributes->_length; ++j) {
pidnames[j]._name = attributes->_buffer[j];
pidnames[j]._pid = shaper->findAttributePathByName(shaper, pidnames[j]._name);
if (create) {
pidnames[j]._pid = shaper->findOrCreateAttributePathByName(shaper, pidnames[j]._name, true);
}
else {
pidnames[j]._pid = shaper->lookupAttributePathByName(shaper, pidnames[j]._name);
}
if (pidnames[j]._pid == 0) {
TRI_Free(TRI_CORE_MEM_ZONE, pidnames);
@ -4270,7 +4277,13 @@ int TRI_PidNamesByAttributeNames (TRI_vector_pointer_t const* attributes,
TRI_shape_pid_t pid;
name = attributes->_buffer[j];
pid = shaper->findAttributePathByName(shaper, name);
if (create) {
pid = shaper->findOrCreateAttributePathByName(shaper, name, true);
}
else {
pid = shaper->lookupAttributePathByName(shaper, name);
}
if (pid == 0) {
TRI_DestroyVector(pids);
@ -4550,7 +4563,7 @@ static TRI_index_t* CreateGeoIndexDocumentCollection (TRI_document_collection_t*
shaper = primary->_shaper;
if (location != NULL) {
loc = shaper->findAttributePathByName(shaper, location);
loc = shaper->findOrCreateAttributePathByName(shaper, location, true);
if (loc == 0) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
@ -4559,7 +4572,7 @@ static TRI_index_t* CreateGeoIndexDocumentCollection (TRI_document_collection_t*
}
if (latitude != NULL) {
lat = shaper->findAttributePathByName(shaper, latitude);
lat = shaper->findOrCreateAttributePathByName(shaper, latitude, true);
if (lat == 0) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
@ -4568,7 +4581,7 @@ static TRI_index_t* CreateGeoIndexDocumentCollection (TRI_document_collection_t*
}
if (longitude != NULL) {
lon = shaper->findAttributePathByName(shaper, longitude);
lon = shaper->findOrCreateAttributePathByName(shaper, longitude, true);
if (lon == 0) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
@ -4817,10 +4830,9 @@ TRI_index_t* TRI_LookupGeoIndex1DocumentCollection (TRI_document_collection_t* d
shaper = document->base._shaper;
loc = shaper->findAttributePathByName(shaper, location);
loc = shaper->lookupAttributePathByName(shaper, location);
if (loc == 0) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
@ -4863,11 +4875,10 @@ TRI_index_t* TRI_LookupGeoIndex2DocumentCollection (TRI_document_collection_t* d
shaper = document->base._shaper;
lat = shaper->findAttributePathByName(shaper, latitude);
lon = shaper->findAttributePathByName(shaper, longitude);
lat = shaper->lookupAttributePathByName(shaper, latitude);
lon = shaper->lookupAttributePathByName(shaper, longitude);
if (lat == 0 || lon == 0) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
@ -5030,11 +5041,12 @@ static TRI_index_t* CreateHashIndexDocumentCollection (TRI_document_collection_t
idx = NULL;
// determine the sorted shape ids for the attributes
res = TRI_PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
true);
res = PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
true,
true);
if (res != TRI_ERROR_NO_ERROR) {
if (created != NULL) {
@ -5142,19 +5154,17 @@ TRI_index_t* TRI_LookupHashIndexDocumentCollection (TRI_document_collection_t* d
TRI_vector_pointer_t const* attributes,
bool unique) {
TRI_index_t* idx;
TRI_primary_collection_t* primary;
TRI_vector_pointer_t fields;
TRI_vector_t paths;
int res;
primary = &document->base;
// determine the sorted shape ids for the attributes
res = TRI_PidNamesByAttributeNames(attributes,
primary->_shaper,
&paths,
&fields,
true);
res = PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
true,
false);
if (res != TRI_ERROR_NO_ERROR) {
return NULL;
@ -5249,11 +5259,12 @@ static TRI_index_t* CreateSkiplistIndexDocumentCollection (TRI_document_collecti
TRI_vector_t paths;
int res;
res = TRI_PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
false);
res = PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
false,
true);
if (res != TRI_ERROR_NO_ERROR) {
if (created != NULL) {
@ -5354,19 +5365,17 @@ TRI_index_t* TRI_LookupSkiplistIndexDocumentCollection (TRI_document_collection_
TRI_vector_pointer_t const* attributes,
bool unique) {
TRI_index_t* idx;
TRI_primary_collection_t* primary;
TRI_vector_pointer_t fields;
TRI_vector_t paths;
int res;
primary = &document->base;
// determine the unsorted shape ids for the attributes
res = TRI_PidNamesByAttributeNames(attributes,
primary->_shaper,
&paths,
&fields,
false);
res = PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
false,
false);
if (res != TRI_ERROR_NO_ERROR) {
return NULL;
@ -5738,11 +5747,12 @@ static TRI_index_t* CreateBitarrayIndexDocumentCollection (TRI_document_collecti
TRI_vector_t paths;
int res;
res = TRI_PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
false);
res = PidNamesByAttributeNames(attributes,
document->base._shaper,
&paths,
&fields,
false,
true);
if (res != TRI_ERROR_NO_ERROR) {
if (created != NULL) {
@ -5883,7 +5893,12 @@ TRI_index_t* TRI_LookupBitarrayIndexDocumentCollection (TRI_document_collection_
// determine the unsorted shape ids for the attributes
// ...........................................................................
result = TRI_PidNamesByAttributeNames(attributes, primary->_shaper, &paths, &fields, false);
result = PidNamesByAttributeNames(attributes,
primary->_shaper,
&paths,
&fields,
false,
false);
if (result != TRI_ERROR_NO_ERROR) {
return NULL;

View File

@ -558,16 +558,6 @@ struct TRI_index_s* TRI_EnsureGeoIndex2DocumentCollection (TRI_document_collecti
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief converts attribute names to sorted lists of pids and names
////////////////////////////////////////////////////////////////////////////////
int TRI_PidNamesByAttributeNames (TRI_vector_pointer_t const*,
TRI_shaper_t*,
TRI_vector_t*,
TRI_vector_pointer_t*,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief finds a hash index
///

View File

@ -1031,8 +1031,7 @@ static int FillLookupSLOperator (TRI_index_operator_t* slOperator,
case TRI_AND_INDEX_OPERATOR:
case TRI_NOT_INDEX_OPERATOR:
case TRI_OR_INDEX_OPERATOR: {
logicalOperator = (TRI_logical_index_operator_t*)(slOperator);
logicalOperator = (TRI_logical_index_operator_t*) slOperator;
result = FillLookupSLOperator(logicalOperator->_left, primary);
if (result == TRI_ERROR_NO_ERROR) {
result = FillLookupSLOperator(logicalOperator->_right, primary);
@ -1049,19 +1048,29 @@ static int FillLookupSLOperator (TRI_index_operator_t* slOperator,
case TRI_NE_INDEX_OPERATOR:
case TRI_LE_INDEX_OPERATOR:
case TRI_LT_INDEX_OPERATOR: {
relationOperator = (TRI_relation_index_operator_t*)(slOperator);
relationOperator = (TRI_relation_index_operator_t*) slOperator;
relationOperator->_numFields = relationOperator->_parameters->_value._objects._length;
relationOperator->_fields = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_shaped_json_t) * relationOperator->_numFields, false);
if (relationOperator->_fields != NULL) {
for (j = 0; j < relationOperator->_numFields; ++j) {
jsonObject = (TRI_json_t*) (TRI_AtVector(&(relationOperator->_parameters->_value._objects),j));
shapedObject = TRI_ShapedJsonJson(primary->_shaper, jsonObject);
if (shapedObject) {
jsonObject = (TRI_json_t*) (TRI_AtVector(&(relationOperator->_parameters->_value._objects), j));
if ((TRI_IsListJson(jsonObject) || TRI_IsArrayJson(jsonObject)) &&
slOperator->_type != TRI_EQ_INDEX_OPERATOR) {
// non-equality operator used on complex data type, this is disallowed
return TRI_ERROR_BAD_PARAMETER;
}
shapedObject = TRI_ShapedJsonJson(primary->_shaper, jsonObject, false, false);
if (shapedObject != NULL) {
relationOperator->_fields[j] = *shapedObject; // shallow copy here is ok
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shapedObject); // don't require storage anymore
}
else {
return TRI_RESULT_ELEMENT_NOT_FOUND;
}
}
}
else {
@ -1069,103 +1078,6 @@ static int FillLookupSLOperator (TRI_index_operator_t* slOperator,
}
break;
}
// .........................................................................
// This index operator is special
// The parameters are given to us as a list of json objects for EQ(...),
// however for the IN(...) operator each parameter in the parameters list
// is itself a list. For skiplists, the number of parameters is a
// decreasing sequence. That is, for a skiplist with 3 attributes,
// the parameters [ ["a","b","c","d"],["x","y"],[0] ] are allowed, whereas
// the parameters [ ["a","b","c"], ["x","y"], [0,1,2] ] are not allowed.
// .........................................................................
case TRI_IN_INDEX_OPERATOR: {
int maxEntries;
relationOperator = (TRI_relation_index_operator_t*)(slOperator);
relationOperator->_numFields = 0;
relationOperator->_fields = NULL;
// .......................................................................
// check that the parameters field is not null
// .......................................................................
if (relationOperator->_parameters == NULL) {
LOG_WARNING("No parameters given when using Skiplist lookup index");
return TRI_ERROR_INTERNAL;
}
// .......................................................................
// check that the parameters json object is of the type list
// .......................................................................
if (relationOperator->_parameters->_type != TRI_JSON_LIST) {
LOG_WARNING("Format of parameters given when using Skiplist lookup index are invalid (a)");
return TRI_ERROR_INTERNAL;
}
// .......................................................................
// Each entry in the list is itself a list
// .......................................................................
relationOperator->_numFields = relationOperator->_parameters->_value._objects._length;
relationOperator->_fields = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_shaped_json_t) * relationOperator->_numFields, false);
if (relationOperator->_fields == NULL) {
relationOperator->_numFields = 0; // out of memory?
return TRI_ERROR_OUT_OF_MEMORY;
}
result = 0;
maxEntries = -1;
for (j = 0; j < relationOperator->_numFields; ++j) {
jsonObject = (TRI_json_t*) (TRI_AtVector(&(relationOperator->_parameters->_value._objects),j));
if (jsonObject == NULL) {
result = -1;
break;
}
if (jsonObject->_type != TRI_JSON_LIST) {
result = -2;
break;
}
// check and see that entries are non-increasing
if ((int) jsonObject->_value._objects._length > maxEntries) {
if (maxEntries > 0) {
result = -3;
break;
}
maxEntries = (int) jsonObject->_value._objects._length;
}
// convert json to shaped json
shapedObject = TRI_ShapedJsonJson(primary->_shaper, jsonObject);
if (shapedObject == NULL) {
result = -4;
break;
}
// store shaped json list
relationOperator->_fields[j] = *shapedObject; // shallow copy here is ok
TRI_Free(TRI_UNKNOWN_MEM_ZONE, shapedObject); // don't require storage anymore
}
if (result != 0) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE,relationOperator->_fields);
relationOperator->_fields = NULL;
relationOperator->_numFields = 0;
LOG_WARNING("Format of parameters given when using Skiplist lookup index are invalid (b)");
return TRI_ERROR_INTERNAL;
}
}
}
return TRI_ERROR_NO_ERROR;
@ -1199,11 +1111,14 @@ TRI_skiplist_iterator_t* TRI_LookupSkiplistIndex (TRI_index_t* idx,
errorResult = FillLookupSLOperator(slOperator, skiplistIndex->base._collection);
if (errorResult != TRI_ERROR_NO_ERROR) {
TRI_set_errno(errorResult);
return NULL;
}
iteratorResult = SkiplistIndex_find(skiplistIndex->_skiplistIndex,
&skiplistIndex->_paths, slOperator);
&skiplistIndex->_paths,
slOperator);
// .........................................................................
// we must deallocate any memory we allocated in FillLookupSLOperator
@ -1837,7 +1752,7 @@ TRI_index_t* TRI_CreateFulltextIndex (struct TRI_primary_collection_s* primary,
// look up the attribute
shaper = primary->_shaper;
attribute = shaper->findAttributePathByName(shaper, attributeName);
attribute = shaper->findOrCreateAttributePathByName(shaper, attributeName, true);
if (attribute == 0) {
return NULL;
@ -1991,14 +1906,6 @@ static int FillLookupBitarrayOperator(TRI_index_operator_t* indexOperator, TRI_p
}
// .........................................................................
// This index operator is special
// .........................................................................
case TRI_IN_INDEX_OPERATOR: {
assert(false);
}
}
return TRI_ERROR_NO_ERROR;

View File

@ -440,6 +440,7 @@ static int LogEvent (TRI_replication_logger_t* logger,
int res;
bool forceSync;
bool withTid;
bool lock;
assert(logger != NULL);
assert(buffer != NULL);
@ -506,10 +507,12 @@ static int LogEvent (TRI_replication_logger_t* logger,
(unsigned long long) tid,
(int) forceSync,
TRI_BeginStringBuffer(buffer));
lock = isStandaloneOperation;
primary = logger->_trxCollection->_collection->_collection;
zone = primary->_shaper->_memoryZone;
shaped = TRI_ShapedJsonJson(primary->_shaper, &json);
shaped = TRI_ShapedJsonJson(primary->_shaper, &json, true, ! lock);
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &json);
ReturnBuffer(logger, buffer);
@ -525,7 +528,7 @@ static int LogEvent (TRI_replication_logger_t* logger,
TRI_DOC_MARKER_KEY_DOCUMENT,
shaped,
NULL,
isStandaloneOperation,
lock,
forceSync,
false);

View File

@ -426,7 +426,7 @@ static int InsertTrxCallback (TRI_transaction_collection_t* trxCollection,
return TRI_ERROR_OUT_OF_MEMORY;
}
shaped = TRI_ShapedJsonJson(primary->_shaper, coordinator->_json);
shaped = TRI_ShapedJsonJson(primary->_shaper, coordinator->_json, true, true);
if (shaped == NULL) {
return TRI_ERROR_OUT_OF_MEMORY;

View File

@ -343,9 +343,30 @@ static void FullSetAttributeWeight (voc_shaper_t* shaper) {
/// @brief finds an attribute identifier by name
////////////////////////////////////////////////////////////////////////////////
static TRI_shape_aid_t FindAttributeByName (TRI_shaper_t* shaper,
char const* name,
bool create) {
static TRI_shape_aid_t LookupAttributeByName (TRI_shaper_t* shaper,
char const* name) {
voc_shaper_t* s;
void const* p;
assert(name != NULL);
s = (voc_shaper_t*) shaper;
p = TRI_LookupByKeyAssociativeSynced(&s->_attributeNames, name);
if (p != NULL) {
return ((TRI_df_attribute_marker_t const*) p)->_aid;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief finds an attribute identifier by name
////////////////////////////////////////////////////////////////////////////////
static TRI_shape_aid_t FindOrCreateAttributeByName (TRI_shaper_t* shaper,
char const* name,
bool isLocked) {
char* mem;
TRI_df_attribute_marker_t* marker;
TRI_df_marker_t* result;
@ -372,10 +393,6 @@ static TRI_shape_aid_t FindAttributeByName (TRI_shaper_t* shaper,
return ((TRI_df_attribute_marker_t const*) p)->_aid;
}
if (! create) {
return 0;
}
// create a new attribute name
n = strlen(name) + 1;
@ -415,9 +432,18 @@ static TRI_shape_aid_t FindAttributeByName (TRI_shaper_t* shaper,
// get next attribute id and write into marker
aid = s->_nextAid++;
marker->_aid = aid;
if (! isLocked) {
// write-lock
s->_collection->base.beginWrite(&s->_collection->base);
}
// write attribute into the collection
res = TRI_WriteMarkerDocumentCollection(s->_collection, &marker->base, totalSize, &fid, &result, false);
if (! isLocked) {
s->_collection->base.endWrite(&s->_collection->base);
}
TRI_Free(TRI_UNKNOWN_MEM_ZONE, mem);
@ -548,7 +574,6 @@ static char const* LookupAttributeId (TRI_shaper_t* shaper, TRI_shape_aid_t aid)
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up an attribute weight by identifier
////////////////////////////////////////////////////////////////////////////////
@ -617,7 +642,9 @@ static bool EqualElementShape (TRI_associative_synced_t* array, void const* left
////////////////////////////////////////////////////////////////////////////////
static TRI_shape_t const* FindShape (TRI_shaper_t* shaper,
TRI_shape_t* shape) {
TRI_shape_t* shape,
bool create,
bool isLocked) {
char* mem;
TRI_df_marker_t* result;
TRI_df_shape_marker_t* marker;
@ -645,6 +672,11 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper,
return found;
}
// not found
if (! create) {
return 0;
}
// initialise a new shape marker
totalSize = sizeof(TRI_df_shape_marker_t) + shape->_size;
mem = (char*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, totalSize, false);
@ -681,9 +713,19 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper,
// get next shape number and write into marker
((TRI_shape_t*) (mem + sizeof(TRI_df_shape_marker_t)))->_sid = s->_nextSid++;
if (! isLocked) {
// write-lock
s->_collection->base.beginWrite(&s->_collection->base);
}
// write shape into the collection
res = TRI_WriteMarkerDocumentCollection(s->_collection, &marker->base, totalSize, &fid, &result, false);
if (! isLocked) {
// write-unlock
s->_collection->base.endWrite(&s->_collection->base);
}
if (res != TRI_ERROR_NO_ERROR) {
TRI_UnlockMutex(&s->_shapeLock);
@ -953,10 +995,11 @@ static uint64_t HashElementWeightedAttribute (TRI_associative_pointer_t* array,
static int InitStep1VocShaper (voc_shaper_t* shaper) {
int res;
shaper->base.findAttributeByName = FindAttributeByName;
shaper->base.lookupAttributeId = LookupAttributeId;
shaper->base.findShape = FindShape;
shaper->base.lookupShapeId = LookupShapeId;
shaper->base.findOrCreateAttributeByName = FindOrCreateAttributeByName;
shaper->base.lookupAttributeByName = LookupAttributeByName;
shaper->base.lookupAttributeId = LookupAttributeId;
shaper->base.findShape = FindShape;
shaper->base.lookupShapeId = LookupShapeId;
res = TRI_InitAssociativeSynced(&shaper->_attributeNames,
TRI_UNKNOWN_MEM_ZONE,

View File

@ -60,8 +60,8 @@ severity = human
file = @LOCALSTATEDIR@/log/arangodb/arangod.log
[cluster]
disable-dispatcher-kickstarter = false
disable-dispatcher-frontend = false
disable-dispatcher-kickstarter = yes
disable-dispatcher-frontend = yes
data-path = @LOCALSTATEDIR@/lib/arangodb/cluster
log-path = @LOCALSTATEDIR@/log/arangodb/cluster
agent-path = @LIBEXECDIR@/arangodb/etcd-arango@PROGRAM_SUFFIX@

View File

@ -19,19 +19,21 @@
var i,j,r;
r = this.get("runInfo");
j = r.length-1;
while (j > 0 && r[j].isStartServers === undefined) {
j--;
}
var l = r[j];
if (l.endpoints) {
for (i = 0; i < l.endpoints.length;i++) {
if (l.roles[i] === "Coordinator") {
this._coord = l.endpoints[i]
.replace("tcp://","http://")
.replace("ssl://", "https://");
return this._coord;
while (j > 0) {
if(r[j].isStartServers) {
var l = r[j];
if (l.endpoints) {
for (i = 0; i < l.endpoints.length;i++) {
if (l.roles[i] === "Coordinator") {
this._coord = l.endpoints[i]
.replace("tcp://","http://")
.replace("ssl://", "https://");
return this._coord;
}
}
}
}
j--;
}
},

View File

@ -14,10 +14,10 @@
<% if (!isSymmetric) { %>
<div class="controls">
<label class="checkbox inline">
<input type="checkbox" value="isCoordinator" class="isCoordinator" checked> Coordinator
<input type="checkbox" value="isCoordinator" class="isCoordinator" checked="checked"> Coordinator
</label>
<label class="checkbox inline">
<input type="checkbox" value="isDBServer" class="isDBServer" checked> DBServer
<input type="checkbox" value="isDBServer" class="isDBServer" checked="checked"> DBServer
</label>
</div>
<% } %>

View File

@ -17,8 +17,6 @@
},
startPlan: function() {
$('#waitModalLayer').modal('show');
$('#waitModalMessage').html('Please be patient while your cluster will be launched');
var isDBServer;
var isCoordinator;
var self = this;
@ -33,8 +31,8 @@
}
var hostObject = {host : host + ":" + port};
if (!self.isSymmetric) {
hostObject.isDBServer = !!$(".isDBServer", dispatcher).attr('checked');
hostObject.isCoordinator = !!$(".isCoordinator", dispatcher).attr('checked');
hostObject.isDBServer = !!$(".isDBServer", dispatcher).prop('checked');
hostObject.isCoordinator = !!$(".isCoordinator", dispatcher).prop('checked');
} else {
hostObject.isDBServer = true;
hostObject.isCoordinator = true;
@ -63,6 +61,8 @@
}
data.type = this.isSymmetric ? "symmetricalSetup" : "asymmetricalSetup";
$('#waitModalLayer').modal('show');
$('#waitModalMessage').html('Please be patient while your cluster will be launched');
this.model.save(
data,
{

View File

@ -226,13 +226,12 @@
if (endDate) {
filterString += " filter u.time < " + endDate;
}
var returnValue = " return u"
var returnValue = " return u";
if (figures) {
var returnValue = " return {time : u.time, server : {uptime : u.server.uptime} ,"
returnValue = " return {time : u.time, server : {uptime : u.server.uptime} ,";
var groups = {};
figures.forEach(function(f) {
var g = f.split(".")[0];
console.log("ggg", g);
if (!groups[g]) {
groups[g] = [];
}

View File

@ -30,6 +30,7 @@
var jsunity = require("jsunity");
var internal = require("internal");
var errors = internal.errors;
// -----------------------------------------------------------------------------
// --SECTION-- basic methods
@ -253,10 +254,22 @@ function SkipListSuite() {
var val = values[i].a;
var expect = documents.slice(i);
var res = collection.byConditionSkiplist(idx.id, { a: [[">=", val]] }, 0, null ).toArray();
var result = res.map(function(a) { return a._key; });
var isValid = ! ((val !== null && typeof val === 'object'));
if (isValid) {
var res = collection.byConditionSkiplist(idx.id, { a: [[">=", val]] }).toArray();
var result = res.map(function(a) { return a._key; });
assertEqual([i, ">=", expect], [i, ">=", result]);
assertEqual([i, ">=", expect], [i, ">=", result]);
}
else {
try {
collection.byConditionSkiplist(idx.id, { a: [[">=", val]] }).toArray();
fail();
}
catch (err1) {
assertEqual(errors.ERROR_ARANGO_NO_INDEX.code, err1.errorNum);
}
}
}
// GREATER THAN
@ -264,10 +277,22 @@ function SkipListSuite() {
var val = values[i].a;
var expect = documents.slice(i + 1);
var res = collection.byConditionSkiplist(idx.id, { a: [[">", val]] }, 0, null ).toArray();
var result = res.map(function(a) { return a._key; });
var isValid = ! ((val !== null && typeof val === 'object'));
if (isValid) {
var res = collection.byConditionSkiplist(idx.id, { a: [[">", val]] }).toArray();
var result = res.map(function(a) { return a._key; });
assertEqual([i, ">", expect], [i, ">", result]);
assertEqual([i, ">", expect], [i, ">", result]);
}
else {
try {
collection.byConditionSkiplist(idx.id, { a: [[">", val]] }).toArray();
fail();
}
catch (err2) {
assertEqual(errors.ERROR_ARANGO_NO_INDEX.code, err2.errorNum);
}
}
}
// LESS THAN OR EQUAL
@ -275,10 +300,22 @@ function SkipListSuite() {
var val = values[i].a;
var expect = documents.slice(1, i + 1);
var res = collection.byConditionSkiplist(idx.id, { a: [["<=", val]] }, 0, null ).toArray();
var result = res.map(function(a) { return a._key; });
var isValid = ! ((val !== null && typeof val === 'object'));
if (isValid) {
var res = collection.byConditionSkiplist(idx.id, { a: [["<=", val]] }).toArray();
var result = res.map(function(a) { return a._key; });
assertEqual([i, "<=", expect], [i, "<=", result]);
assertEqual([i, "<=", expect], [i, "<=", result]);
}
else {
try {
collection.byConditionSkiplist(idx.id, { a: [["<=", val]] }).toArray();
fail();
}
catch (err3) {
assertEqual(errors.ERROR_ARANGO_NO_INDEX.code, err3.errorNum);
}
}
}
@ -287,10 +324,22 @@ function SkipListSuite() {
var val = values[i].a;
var expect = documents.slice(1, i);
var res = collection.byConditionSkiplist(idx.id, { a: [["<", val]] }, 0, null ).toArray();
var result = res.map(function(a) { return a._key; });
var isValid = ! ((val !== null && typeof val === 'object'));
if (isValid) {
var res = collection.byConditionSkiplist(idx.id, { a: [["<", val]] }).toArray();
var result = res.map(function(a) { return a._key; });
assertEqual([i, "<", expect], [i, "<", result]);
assertEqual([i, "<", expect], [i, "<", result]);
}
else {
try {
collection.byConditionSkiplist(idx.id, { a: [["<", val]] }).toArray();
fail();
}
catch (err4) {
assertEqual(errors.ERROR_ARANGO_NO_INDEX.code, err4.errorNum);
}
}
}
// BETWEEN
@ -300,11 +349,27 @@ function SkipListSuite() {
for (j = 1; j < documents.length; ++j) {
var valj = values[j].a;
var expect = documents.slice(i, j + 1);
var isValid = ! ((vali !== null && typeof vali === 'object'));
if (isValid) {
isValid &= ! ((valj !== null && typeof valj === 'object'));
}
var res = collection.byConditionSkiplist(idx.id, { a: [[">=", vali], ["<=", valj]] }, 0, null ).toArray();
var result = res.map(function(a) { return a._key; });
if (isValid) {
var res = collection.byConditionSkiplist(idx.id, { a: [[">=", vali], ["<=", valj]] }).toArray();
var result = res.map(function(a) { return a._key; });
assertEqual([i, ">= <=", expect], [i, ">= <=", result]);
assertEqual([i, ">= <=", expect], [i, ">= <=", result]);
}
else {
try {
collection.byConditionSkiplist(idx.id, { a: [[">=", vali], ["<=", valj]] }).toArray();
fail();
}
catch (err5) {
assertEqual(errors.ERROR_ARANGO_NO_INDEX.code, err5.errorNum);
}
}
}
}
}

View File

@ -179,7 +179,8 @@ static bool EqualNameKeyAttributePath (TRI_associative_synced_t* array, void con
static TRI_shape_path_t const* FindShapePathByName (TRI_shaper_t* shaper,
char const* name,
bool create) {
bool create,
bool isLocked) {
TRI_shape_aid_t* aids;
TRI_shape_path_t* result;
size_t count;
@ -242,10 +243,10 @@ static TRI_shape_path_t const* FindShapePathByName (TRI_shaper_t* shaper,
if (ptr != prev) {
if (create) {
aids[count++] = shaper->findAttributeByName(shaper, prev, true);
aids[count++] = shaper->findOrCreateAttributeByName(shaper, prev, isLocked);
}
else {
aids[count] = shaper->findAttributeByName(shaper, prev, false);
aids[count] = shaper->lookupAttributeByName(shaper, prev);
if (aids[count] == 0) {
TRI_FreeString(shaper->_memoryZone, buffer);
@ -299,8 +300,10 @@ static TRI_shape_path_t const* FindShapePathByName (TRI_shaper_t* shaper,
/// @brief finds an attribute path by identifier
////////////////////////////////////////////////////////////////////////////////
static TRI_shape_pid_t FindAttributePathByName (TRI_shaper_t* shaper, char const* name) {
TRI_shape_path_t const* path = FindShapePathByName(shaper, name, true);
static TRI_shape_pid_t FindOrCreateAttributePathByName (TRI_shaper_t* shaper,
char const* name,
bool isLocked) {
TRI_shape_path_t const* path = FindShapePathByName(shaper, name, true, isLocked);
return path == NULL ? 0 : path->_pid;
}
@ -309,8 +312,9 @@ static TRI_shape_pid_t FindAttributePathByName (TRI_shaper_t* shaper, char const
/// @brief looks up an attribute path by identifier
////////////////////////////////////////////////////////////////////////////////
static TRI_shape_pid_t LookupAttributePathByName (TRI_shaper_t* shaper, char const* name) {
TRI_shape_path_t const* path = FindShapePathByName(shaper, name, false);
static TRI_shape_pid_t LookupAttributePathByName (TRI_shaper_t* shaper,
char const* name) {
TRI_shape_path_t const* path = FindShapePathByName(shaper, name, false, true);
return path == NULL ? 0 : path->_pid;
}
@ -327,7 +331,8 @@ static TRI_shape_pid_t LookupAttributePathByName (TRI_shaper_t* shaper, char con
/// @brief creates the attribute path
////////////////////////////////////////////////////////////////////////////////
char const* TRI_AttributeNameShapePid (TRI_shaper_t* shaper, TRI_shape_pid_t pid) {
char const* TRI_AttributeNameShapePid (TRI_shaper_t* shaper,
TRI_shape_pid_t pid) {
TRI_shape_path_t const* path;
char const* e;
@ -379,7 +384,7 @@ int TRI_InitShaper (TRI_shaper_t* shaper, TRI_memory_zone_t* zone) {
shaper->_nextPid = 1;
shaper->lookupAttributePathByPid = LookupPidAttributePath;
shaper->findAttributePathByName = FindAttributePathByName;
shaper->findOrCreateAttributePathByName = FindOrCreateAttributePathByName;
shaper->lookupAttributePathByName = LookupAttributePathByName;
return TRI_ERROR_NO_ERROR;

View File

@ -91,13 +91,14 @@ TRI_basic_shapes_t;
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_shaper_s {
TRI_shape_aid_t (*findAttributeByName) (struct TRI_shaper_s*, char const*, bool);
TRI_shape_aid_t (*findOrCreateAttributeByName) (struct TRI_shaper_s*, char const*, bool);
TRI_shape_aid_t (*lookupAttributeByName) (struct TRI_shaper_s*, char const*);
char const* (*lookupAttributeId) (struct TRI_shaper_s*, TRI_shape_aid_t);
TRI_shape_t const* (*findShape) (struct TRI_shaper_s*, TRI_shape_t*);
TRI_shape_t const* (*findShape) (struct TRI_shaper_s*, TRI_shape_t*, bool, bool);
TRI_shape_t const* (*lookupShapeId) (struct TRI_shaper_s*, TRI_shape_sid_t);
int64_t (*lookupAttributeWeight) (struct TRI_shaper_s*, TRI_shape_aid_t);
TRI_shape_path_t const* (*lookupAttributePathByPid) (struct TRI_shaper_s*, TRI_shape_pid_t);
TRI_shape_pid_t (*findAttributePathByName) (struct TRI_shaper_s*, char const*);
TRI_shape_pid_t (*findOrCreateAttributePathByName) (struct TRI_shaper_s*, char const*, bool);
TRI_shape_pid_t (*lookupAttributePathByName) (struct TRI_shaper_s*, char const*);
TRI_associative_synced_t _attributePathsByName;

View File

@ -42,7 +42,7 @@
// --SECTION-- forward declarations
// -----------------------------------------------------------------------------
static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json);
static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json, bool, bool);
static TRI_json_t* JsonShapeData (TRI_shaper_t* shaper, TRI_shape_t const* shape, char const* data, uint64_t size);
static bool StringifyJsonShapeData (TRI_shaper_t* shaper, TRI_string_buffer_t* buffer, TRI_shape_t const* shape, char const* data, uint64_t size);
@ -463,7 +463,11 @@ static bool FillShapeValueString (TRI_shaper_t* shaper, TRI_shape_value_t* dst,
/// @brief converts a json list into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueList (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json) {
static bool FillShapeValueList (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
TRI_json_t const* json,
bool create,
bool isLocked) {
size_t i, n;
uint64_t total;
@ -520,7 +524,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TR
for (i = 0; i < n; ++i, ++p) {
TRI_json_t const* el = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i);
bool ok = FillShapeValueJson(shaper, p, el);
bool ok = FillShapeValueJson(shaper, p, el, create, isLocked);
if (! ok) {
for (e = p, p = values; p < e; ++p) {
@ -580,7 +584,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TR
shape->_sidEntry = s;
shape->_sizeEntry = l;
found = shaper->findShape(shaper, &shape->base);
found = shaper->findShape(shaper, &shape->base, create, isLocked);
if (found == NULL) {
for (p = values; p < e; ++p) {
@ -649,7 +653,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TR
shape->base._dataSize = TRI_SHAPE_SIZE_VARIABLE;
shape->_sidEntry = s;
found = shaper->findShape(shaper, &shape->base);
found = shaper->findShape(shaper, &shape->base, create, isLocked);
if (found == NULL) {
for (p = values; p < e; ++p) {
@ -770,7 +774,9 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TR
static bool FillShapeValueArray (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
TRI_json_t const* json) {
TRI_json_t const* json,
bool create,
bool isLocked) {
size_t i, n;
uint64_t total;
@ -831,14 +837,14 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
}
// first find an identifier for the name
p->_aid = shaper->findAttributeByName(shaper, key->_value._string.data, true);
p->_aid = shaper->findOrCreateAttributeByName(shaper, key->_value._string.data, isLocked);
// convert value
if (p->_aid == 0) {
ok = false;
}
else {
ok = FillShapeValueJson(shaper, p, val);
ok = FillShapeValueJson(shaper, p, val, create, isLocked);
}
if (! ok) {
@ -987,7 +993,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
// lookup this shape
found = shaper->findShape(shaper, &a->base);
found = shaper->findShape(shaper, &a->base, create, isLocked);
if (found == NULL) {
TRI_Free(shaper->_memoryZone, a);
@ -1003,7 +1009,11 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
/// @brief converts a json object into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json) {
static bool FillShapeValueJson (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
TRI_json_t const* json,
bool create,
bool isLocked) {
switch (json->_type) {
case TRI_JSON_UNUSED:
return false;
@ -1022,10 +1032,10 @@ static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TR
return FillShapeValueString(shaper, dst, json);
case TRI_JSON_ARRAY:
return FillShapeValueArray(shaper, dst, json);
return FillShapeValueArray(shaper, dst, json, create, isLocked);
case TRI_JSON_LIST:
return FillShapeValueList(shaper, dst, json);
return FillShapeValueList(shaper, dst, json, create, isLocked);
}
return false;
@ -2259,13 +2269,15 @@ void TRI_SortShapeValues (TRI_shape_value_t* values,
////////////////////////////////////////////////////////////////////////////////
TRI_shaped_json_t* TRI_ShapedJsonJson (TRI_shaper_t* shaper,
TRI_json_t const* json) {
TRI_json_t const* json,
bool create,
bool isLocked) {
TRI_shaped_json_t* shaped;
TRI_shape_value_t dst;
bool ok;
dst._value = 0;
ok = FillShapeValueJson(shaper, &dst, json);
ok = FillShapeValueJson(shaper, &dst, json, create, isLocked);
if (! ok) {
return NULL;
@ -2296,7 +2308,8 @@ TRI_shaped_json_t* TRI_ShapedJsonJson (TRI_shaper_t* shaper,
/// @brief converts a shaped json object into a json object
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_JsonShapedJson (TRI_shaper_t* shaper, TRI_shaped_json_t const* shaped) {
TRI_json_t* TRI_JsonShapedJson (TRI_shaper_t* shaper,
TRI_shaped_json_t const* shaped) {
TRI_shape_t const* shape;
shape = shaper->lookupShapeId(shaper, shaped->_sid);

View File

@ -954,7 +954,8 @@ void TRI_DestroyShapedJson (struct TRI_memory_zone_s*, TRI_shaped_json_t*);
/// @brief destroys a json object and frees the pointer
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeShapedJson (struct TRI_memory_zone_s*, TRI_shaped_json_t*);
void TRI_FreeShapedJson (struct TRI_memory_zone_s*,
TRI_shaped_json_t*);
////////////////////////////////////////////////////////////////////////////////
/// @}
@ -973,19 +974,24 @@ void TRI_FreeShapedJson (struct TRI_memory_zone_s*, TRI_shaped_json_t*);
/// @brief sorts a list of TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
void TRI_SortShapeValues (TRI_shape_value_t* values, size_t n);
void TRI_SortShapeValues (TRI_shape_value_t* values,
size_t n);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a json object into a shaped json object
////////////////////////////////////////////////////////////////////////////////
TRI_shaped_json_t* TRI_ShapedJsonJson (struct TRI_shaper_s*, TRI_json_t const*);
TRI_shaped_json_t* TRI_ShapedJsonJson (struct TRI_shaper_s*,
TRI_json_t const*,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a shaped json object into a json object
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_JsonShapedJson (struct TRI_shaper_s*, TRI_shaped_json_t const*);
TRI_json_t* TRI_JsonShapedJson (struct TRI_shaper_s*,
TRI_shaped_json_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief prints a shaped json to a string buffer, without the outer braces

View File

@ -46,11 +46,13 @@ using namespace triagens::basics;
// --SECTION-- forward declarations
// -----------------------------------------------------------------------------
static bool FillShapeValueJson (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Value> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects);
static int FillShapeValueJson (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Value> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked);
static v8::Handle<v8::Value> JsonShapeData (TRI_shaper_t* shaper,
TRI_shape_t const* shape,
@ -83,7 +85,7 @@ shape_cache_t;
/// @brief converts a null into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueNull (TRI_shaper_t* shaper,
static int FillShapeValueNull (TRI_shaper_t* shaper,
TRI_shape_value_t* dst) {
dst->_type = TRI_SHAPE_NULL;
dst->_sid = TRI_LookupBasicSidShaper(TRI_SHAPE_NULL);
@ -91,16 +93,16 @@ static bool FillShapeValueNull (TRI_shaper_t* shaper,
dst->_size = 0;
dst->_value = 0;
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a boolean into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueBoolean (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Boolean> const& json) {
static int FillShapeValueBoolean (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Boolean> const& json) {
TRI_shape_boolean_t* ptr;
dst->_type = TRI_SHAPE_BOOLEAN;
@ -109,22 +111,22 @@ static bool FillShapeValueBoolean (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_boolean_t);
dst->_value = (char*) (ptr = (TRI_shape_boolean_t*) TRI_Allocate(shaper->_memoryZone, dst->_size, false));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
*ptr = json->Value() ? 1 : 0;
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a boolean into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueBoolean (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::BooleanObject> const& json) {
static int FillShapeValueBoolean (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::BooleanObject> const& json) {
TRI_shape_boolean_t* ptr;
dst->_type = TRI_SHAPE_BOOLEAN;
@ -133,22 +135,22 @@ static bool FillShapeValueBoolean (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_boolean_t);
dst->_value = (char*) (ptr = (TRI_shape_boolean_t*) TRI_Allocate(shaper->_memoryZone, dst->_size, false));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
*ptr = json->BooleanValue() ? 1 : 0;
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a number into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueNumber (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Number> const& json) {
static int FillShapeValueNumber (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Number> const& json) {
TRI_shape_number_t* ptr;
dst->_type = TRI_SHAPE_NUMBER;
@ -157,22 +159,22 @@ static bool FillShapeValueNumber (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_number_t);
dst->_value = (char*) (ptr = (TRI_shape_number_t*) TRI_Allocate(shaper->_memoryZone, dst->_size, false));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
*ptr = json->Value();
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a number into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueNumber (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::NumberObject> const& json) {
static int FillShapeValueNumber (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::NumberObject> const& json) {
TRI_shape_number_t* ptr;
dst->_type = TRI_SHAPE_NUMBER;
@ -181,22 +183,22 @@ static bool FillShapeValueNumber (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_number_t);
dst->_value = (char*) (ptr = (TRI_shape_number_t*) TRI_Allocate(shaper->_memoryZone, dst->_size, false));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
*ptr = json->NumberValue();
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a string into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueString (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::String> const& json) {
static int FillShapeValueString (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::String> const& json) {
char* ptr;
TRI_Utf8ValueNFC str(TRI_UNKNOWN_MEM_ZONE, json);
@ -208,8 +210,8 @@ static bool FillShapeValueString (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_length_short_string_t) + TRI_SHAPE_SHORT_STRING_CUT;
dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
* ((TRI_shape_length_short_string_t*) ptr) = 1;
@ -225,8 +227,8 @@ static bool FillShapeValueString (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_length_short_string_t) + TRI_SHAPE_SHORT_STRING_CUT;
dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
* ((TRI_shape_length_short_string_t*) ptr) = size + 1;
@ -239,8 +241,8 @@ static bool FillShapeValueString (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_length_long_string_t) + size + 1;
dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
* ((TRI_shape_length_long_string_t*) ptr) = size + 1;
@ -248,18 +250,20 @@ static bool FillShapeValueString (TRI_shaper_t* shaper,
}
}
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a json list into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueList (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Array> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects) {
static int FillShapeValueList (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Array> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked) {
size_t i, n;
size_t total;
@ -292,20 +296,20 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
dst->_size = sizeof(TRI_shape_length_list_t);
dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, false));
if (dst->_value == NULL) {
return false;
if (dst->_value == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
* (TRI_shape_length_list_t*) ptr = 0;
return true;
return TRI_ERROR_NO_ERROR;
}
// convert into TRI_shape_value_t array
p = (values = (TRI_shape_value_t*) TRI_Allocate(shaper->_memoryZone, sizeof(TRI_shape_value_t) * n, true));
if (p == NULL) {
return false;
if (p == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
total = 0;
@ -313,13 +317,9 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
for (i = 0; i < n; ++i, ++p) {
v8::Handle<v8::Value> el = json->Get(i);
bool ok = FillShapeValueJson(shaper, p, el, seenHashes, seenObjects);
if (! ok) {
if (! ok) {
LOG_TRACE("failed to convert position '%d'", (int) i);
}
int res = FillShapeValueJson(shaper, p, el, seenHashes, seenObjects, create, isLocked);
if (res != TRI_ERROR_NO_ERROR) {
for (e = p, p = values; p < e; ++p) {
if (p->_value != 0) {
TRI_Free(shaper->_memoryZone, p->_value);
@ -327,7 +327,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
}
TRI_Free(shaper->_memoryZone, values);
return false;
return res;
}
total += p->_size;
@ -358,7 +358,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
shape = (TRI_homogeneous_sized_list_shape_t*) TRI_Allocate(shaper->_memoryZone, sizeof(TRI_homogeneous_sized_list_shape_t), true);
if (shape == NULL) {
if (shape == 0) {
for (p = values; p < e; ++p) {
if (p->_value != 0) {
TRI_Free(shaper->_memoryZone, p->_value);
@ -366,8 +366,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
}
TRI_Free(shaper->_memoryZone, values);
return false;
return TRI_ERROR_OUT_OF_MEMORY;
}
shape->base._size = sizeof(TRI_homogeneous_sized_list_shape_t);
@ -376,7 +375,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
shape->_sidEntry = s;
shape->_sizeEntry = l;
found = shaper->findShape(shaper, &shape->base);
found = shaper->findShape(shaper, &shape->base, create, isLocked);
if (found == 0) {
for (p = values; p < e; ++p) {
@ -389,7 +388,12 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, shape);
LOG_TRACE("shaper failed to find shape of type %d", (int) shape->base._type);
return false;
if (! create) {
return TRI_RESULT_ELEMENT_NOT_FOUND;
}
return TRI_ERROR_INTERNAL;
}
assert(found != 0);
@ -410,7 +414,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
return false;
return TRI_ERROR_OUT_OF_MEMORY;
}
// copy sub-objects into data space
@ -438,7 +442,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
return false;
return TRI_ERROR_OUT_OF_MEMORY;
}
shape->base._size = sizeof(TRI_homogeneous_list_shape_t);
@ -447,7 +451,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
shape->_sidEntry = s;
// if found returns non-NULL, it will free the shape!!
found = shaper->findShape(shaper, &shape->base);
found = shaper->findShape(shaper, &shape->base, create, isLocked);
if (found == 0) {
for (p = values; p < e; ++p) {
@ -460,7 +464,12 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
TRI_Free(shaper->_memoryZone, shape);
return false;
if (! create) {
return TRI_RESULT_ELEMENT_NOT_FOUND;
}
return TRI_ERROR_INTERNAL;
}
assert(found != 0);
@ -483,7 +492,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
return false;
return TRI_ERROR_OUT_OF_MEMORY;
}
// copy sub-objects into data space
@ -526,7 +535,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
}
TRI_Free(shaper->_memoryZone, values);
return false;
return TRI_ERROR_OUT_OF_MEMORY;
}
// copy sub-objects into data space
@ -560,18 +569,20 @@ static bool FillShapeValueList (TRI_shaper_t* shaper,
}
TRI_Free(shaper->_memoryZone, values);
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a json array into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueArray (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Object> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects) {
static int FillShapeValueArray (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Object> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked) {
size_t i, n;
size_t total;
@ -601,8 +612,8 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
// convert into TRI_shape_value_t array
p = (values = (TRI_shape_value_t*) TRI_Allocate(shaper->_memoryZone, n * sizeof(TRI_shape_value_t), true));
if (p == NULL) {
return false;
if (p == 0) {
return TRI_ERROR_OUT_OF_MEMORY;
}
total = 0;
@ -612,7 +623,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
for (i = 0; i < n; ++i, ++p) {
v8::Handle<v8::Value> key = names->Get(i);
v8::Handle<v8::Value> val = json->Get(key);
bool ok;
int res;
// first find an identifier for the name
TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key);
@ -627,21 +638,27 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
continue;
}
p->_aid = shaper->findAttributeByName(shaper, *keyStr, true);
if (create) {
p->_aid = shaper->findOrCreateAttributeByName(shaper, *keyStr, isLocked);
}
else {
p->_aid = shaper->lookupAttributeByName(shaper, *keyStr);
}
// convert value
if (p->_aid == 0) {
ok = false;
}
else {
ok = FillShapeValueJson(shaper, p, val, seenHashes, seenObjects);
if (! ok) {
LOG_TRACE("failed to convert attribute '%s'", *keyStr);
if (create) {
res = TRI_ERROR_INTERNAL;
}
else {
res = TRI_RESULT_ELEMENT_NOT_FOUND;
}
}
else {
res = FillShapeValueJson(shaper, p, val, seenHashes, seenObjects, create, isLocked);
}
if (! ok) {
if (res != TRI_ERROR_NO_ERROR) {
for (e = p, p = values; p < e; ++p) {
if (p->_value != 0) {
TRI_Free(shaper->_memoryZone, p->_value);
@ -649,7 +666,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
}
TRI_Free(shaper->_memoryZone, values);
return false;
return res;
}
total += p->_size;
@ -703,7 +720,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
return false;
return TRI_ERROR_OUT_OF_MEMORY;
}
a->base._type = TRI_SHAPE_ARRAY;
@ -734,11 +751,11 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
dst->_size = total;
dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true));
if (ptr == NULL) {
if (ptr == 0) {
e = values + n;
for (p = values; p < e; ++p) {
if (p->_value != NULL) {
if (p->_value != 0) {
TRI_Free(shaper->_memoryZone, p->_value);
}
}
@ -746,7 +763,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
TRI_Free(shaper->_memoryZone, a);
return false;
return TRI_ERROR_OUT_OF_MEMORY;
}
// array of offsets for variable part (within the value)
@ -787,30 +804,35 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper,
TRI_Free(shaper->_memoryZone, values);
// lookup this shape
found = shaper->findShape(shaper, &a->base);
found = shaper->findShape(shaper, &a->base, create, isLocked);
if (found == 0) {
LOG_TRACE("shaper failed to find shape %d", (int) a->base._type);
TRI_Free(shaper->_memoryZone, a);
return false;
if (! create) {
return TRI_RESULT_ELEMENT_NOT_FOUND;
}
return TRI_ERROR_INTERNAL;
}
// and finally add the sid
dst->_sid = found->_sid;
return true;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a json object into TRI_shape_value_t
////////////////////////////////////////////////////////////////////////////////
static bool FillShapeValueJson (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Value> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects) {
bool result = false;
static int FillShapeValueJson (TRI_shaper_t* shaper,
TRI_shape_value_t* dst,
v8::Handle<v8::Value> const& json,
set<int>& seenHashes,
vector< v8::Handle<v8::Object> >& seenObjects,
bool create,
bool isLocked) {
// check for cycles
if (json->IsObject()) {
v8::Handle<v8::Object> o = json->ToObject();
@ -822,7 +844,7 @@ static bool FillShapeValueJson (TRI_shaper_t* shaper,
for (vector< v8::Handle<v8::Object> >::iterator i = seenObjects.begin(); i != seenObjects.end(); ++i) {
if (json->StrictEquals(*i)) {
LOG_TRACE("found duplicate for hash %d", hash);
return false;
return TRI_ERROR_ARANGO_SHAPER_FAILED;
}
}
}
@ -834,68 +856,70 @@ static bool FillShapeValueJson (TRI_shaper_t* shaper,
}
if (json->IsNull()) {
result = FillShapeValueNull(shaper, dst);
return FillShapeValueNull(shaper, dst);
}
else if (json->IsBoolean()) {
result = FillShapeValueBoolean(shaper, dst, json->ToBoolean());
return FillShapeValueBoolean(shaper, dst, json->ToBoolean());
}
else if (json->IsBooleanObject()) {
result = FillShapeValueBoolean(shaper, dst, v8::Handle<v8::BooleanObject>::Cast(json));
return FillShapeValueBoolean(shaper, dst, v8::Handle<v8::BooleanObject>::Cast(json));
}
else if (json->IsNumber()) {
result = FillShapeValueNumber(shaper, dst, json->ToNumber());
return FillShapeValueNumber(shaper, dst, json->ToNumber());
}
else if (json->IsNumberObject()) {
result = FillShapeValueNumber(shaper, dst, v8::Handle<v8::NumberObject>::Cast(json));
return FillShapeValueNumber(shaper, dst, v8::Handle<v8::NumberObject>::Cast(json));
}
else if (json->IsString()) {
result = FillShapeValueString(shaper, dst, json->ToString());
return FillShapeValueString(shaper, dst, json->ToString());
}
else if (json->IsStringObject()) {
result = FillShapeValueString(shaper, dst, v8::Handle<v8::StringObject>::Cast(json)->StringValue());
return FillShapeValueString(shaper, dst, v8::Handle<v8::StringObject>::Cast(json)->StringValue());
}
else if (json->IsArray()) {
result = FillShapeValueList(shaper, dst, v8::Handle<v8::Array>::Cast(json), seenHashes, seenObjects);
return FillShapeValueList(shaper, dst, v8::Handle<v8::Array>::Cast(json), seenHashes, seenObjects, create, isLocked);
}
else if (json->IsObject()) {
result = FillShapeValueArray(shaper, dst, json->ToObject(), seenHashes, seenObjects);
else if (json->IsObject()) {
int res = FillShapeValueArray(shaper, dst, json->ToObject(), seenHashes, seenObjects, create, isLocked);
seenObjects.pop_back();
return res;
}
else if (json->IsRegExp()) {
LOG_TRACE("shaper failed because a regexp cannot be converted");
return TRI_ERROR_BAD_PARAMETER;
}
else if (json->IsFunction()) {
LOG_TRACE("shaper failed because a function cannot be converted");
return TRI_ERROR_BAD_PARAMETER;
}
else if (json->IsExternal()) {
LOG_TRACE("shaper failed because an external cannot be converted");
return TRI_ERROR_BAD_PARAMETER;
}
else if (json->IsDate()) {
LOG_TRACE("shaper failed because a date cannot be converted");
return TRI_ERROR_BAD_PARAMETER;
}
// treat undefined as null value
else if (json->IsUndefined()) {
result = FillShapeValueNull(shaper, dst);
return FillShapeValueNull(shaper, dst);
}
else {
LOG_TRACE("shaper failed to convert object");
}
return result;
LOG_TRACE("shaper failed to convert object");
return TRI_ERROR_BAD_PARAMETER;
}
////////////////////////////////////////////////////////////////////////////////
@ -1430,14 +1454,22 @@ v8::Handle<v8::Value> TRI_JsonShapeData (TRI_shaper_t* shaper,
////////////////////////////////////////////////////////////////////////////////
TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle<v8::Value> const& object,
TRI_shaper_t* shaper) {
TRI_shaper_t* shaper,
bool create,
bool isLocked) {
TRI_shape_value_t dst;
set<int> seenHashes;
vector< v8::Handle<v8::Object> > seenObjects;
bool ok = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects);
if (! ok) {
TRI_set_errno(TRI_ERROR_ARANGO_SHAPER_FAILED);
int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create, isLocked);
if (res != TRI_ERROR_NO_ERROR) {
if (res == TRI_RESULT_ELEMENT_NOT_FOUND) {
TRI_set_errno(res);
}
else {
TRI_set_errno(TRI_ERROR_ARANGO_SHAPER_FAILED);
}
return 0;
}
@ -1460,14 +1492,20 @@ TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle<v8::Value> const& object,
int TRI_FillShapedJsonV8Object (v8::Handle<v8::Value> const& object,
TRI_shaped_json_t* result,
TRI_shaper_t* shaper) {
TRI_shaper_t* shaper,
bool create,
bool isLocked) {
TRI_shape_value_t dst;
set<int> seenHashes;
vector< v8::Handle<v8::Object> > seenObjects;
bool ok = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects);
if (! ok) {
return TRI_set_errno(TRI_ERROR_BAD_PARAMETER);
int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create, isLocked);
if (res != TRI_ERROR_NO_ERROR) {
if (res != TRI_RESULT_ELEMENT_NOT_FOUND) {
res = TRI_ERROR_BAD_PARAMETER;
}
return TRI_set_errno(res);
}
result->_sid = dst._sid;

View File

@ -67,15 +67,19 @@ v8::Handle<v8::Value> TRI_JsonShapeData (TRI_shaper_t*,
////////////////////////////////////////////////////////////////////////////////
TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle<v8::Value> const&,
TRI_shaper_t*);
TRI_shaper_t*,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a V8 object to a TRI_shaped_json_t in place
////////////////////////////////////////////////////////////////////////////////
int TRI_FillShapedJsonV8Object (v8::Handle<v8::Value> const& object,
TRI_shaped_json_t* result,
TRI_shaper_t*);
int TRI_FillShapedJsonV8Object (v8::Handle<v8::Value> const&,
TRI_shaped_json_t*,
TRI_shaper_t*,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a V8 value to a json_t value